Mi problema:
Estoy intentando escribir una pequeña aplicación Knockout JS dentro de Magento 2, estoy luchando por inicializar la aplicación, ya que cuando la uso ko.applyBindings(AppViewModel, document.getElementById("koTest"));
rompe la Knockout utilizada por Magento y arroja este error:
Uncaught Error: You cannot apply bindings multiple times to the same element.
Sospecho que es por:
Sospecho que esto se debe a que Magento 2 ya usa ko.applyBindings()
dentro app/code/Magento/Ui/view/base/web/js/lib/knockout/bootstrap.js
. Y como eso no especifica un nodo que no puedo usar de ko.applyBindings
nuevo.
Si no uso ko.applyBindings(AppViewModel, document.getElementById("koTest"))
mi código, entonces mi aplicación no se inicializa.
Esto me hace pensar que necesito usar de alguna manera el ko.applyBindings()
archivo knockout / bootstrap.js pero no tengo idea de cómo, ¿alguien puede ayudarme? Tengo poca experiencia con Knockout.
Mi código
<script type="text/javascript">
require([
'ko'
], function(ko) {
// This is a simple *viewmodel* - JavaScript that defines the data and behavior of your UI
function AppViewModel() {
this.firstName = ko.observable("Bert");
this.lastName = ko.observable("Bertington");
this.fullName = ko.computed(function() {
return this.firstName() + " " + this.lastName();
}, this);
this.capitalizeLastName = function() {
var currentVal = this.lastName();
this.lastName(currentVal.toUpperCase());
};
}
ko.applyBindings(AppViewModel, document.getElementById("koTest"));
});
</script>
<!-- This is a *view* - HTML markup that defines the appearance of your UI -->
<div id="koTest">
<p>First name: <strong data-bind="text: firstName"></strong></p>
<p>Last name: <strong data-bind="text: lastName"></strong></p>
<p>Full name: <strong data-bind="text: fullName"></strong></p>
<p>First name: <input data-bind="value: firstName" /></p>
<p>Last name: <input data-bind="value: lastName" /></p>
<p>Full name: <input data-bind="value: fullName" /></p>
<button data-bind="click: capitalizeLastName">Capitalise</button>
</div>
fuente
Respuestas:
Método simple donde NO necesita usar plantillas html
Gracias a Vinai Kopp, finalmente obtuve una respuesta a esto, es mucho más simple que mi solución alternativa anterior (estaba limpiando nodos). Todo lo que necesita hacer es definir
'ko'
como una dependencia y agregar su código dentro de una función de retorno.A continuación se muestra un ejemplo simple que muestra parte del texto pasado a través de JSON.
app/code/VENODR/MODULE/view/frontend/templates/knockout-example.phtml
Aquí le decimos a Magento el alcance de nuestros componentes (esto debe coincidir
data-bind: "scope: 'example-scope'"
y pasar cualquier información adicional. Esta podría ser la URL base, un mensaje simple, casi cualquier cosa que desee. He pasado una cadena (PHP echo) como ejemploY aquí escribimos nuestro Javascript.
app/code/VENDOR/MODULE/view/frontend/web/js/knockout-example.js
Resultado
---------------------
Método donde necesita usar plantillas HTML
Si desea utilizar el sistema de plantillas HTML dentro de Magento2 / Knockout (que supongo que necesitará para cualquier trabajo significativo), debe realizar algunos cambios en comparación con mi respuesta simplificada (a continuación).
Si no necesita la funcionalidad de la plantilla, desplácese hacia abajo hasta mi antigua respuesta simplificada.
Los archivos que estoy usando para este ejemplo son:
app/design/frontend/VENDOR/THEME/Magento_Cms/templates/knockout.phtml
app/design/frontend/VENDOR/THEME/Magento_Cms/web/js/knockout-example.js
app/design/frontend/VENDOR/THEME/Magento_Cms/web/template/test.html
El archivo de plantilla PHTML
El único cambio en nuestra plantilla PHTML es la llamada a la
getTemplate()
función:El archivo JS (componente)
Hay algunos cambios que deberá realizar en el archivo JS, los detallaré a continuación.
1 - Su función de retorno ahora necesita extender el módulo uiComponent:
2 - Necesita agregar una
initialize
función y llamarthis._super()
.this._super()
llamará a la función del componente principal con el mismo nombre. Así que en este caso lo que se llamaráinitialize
deuiComponent
.3 - Opcional : también puede establecer algunos valores predeterminados para su componente aquí, creo que es una buena práctica a seguir, ya que hace que su componente sea fácil de trabajar. Cuando lo reutiliza, puede mantener los valores predeterminados o, si desea personalizarlo, puede llamarlo con nuevos argumentos sin alterar el componente.
Por ejemplo, si nos fijamos en los valores predeterminados de la JS establece
exampleMessage
que'Hello?'
sin embargo, la página se visualice el textoHello Magento Stack Exchange!
. Esto se debe a que he sobrescritoexampleMessage
en el archivo PHTML cuando llamé al componente.La plantilla HTML
Todavía tengo que investigar y ver de qué son capaces las plantillas HTML, supongo que las características mencionadas en la documentación de Knockout JS se pueden usar aquí, lo que las hace bastante flexibles.
Acabo de agregar un poco de texto lorem ipsum por ahora, probablemente proporcionaré otra pregunta / respuesta una vez que haya descubierto lo que pueden hacer las plantillas HTML.
El resultado y sobrescribir los valores predeterminados
Como se mencionó anteriormente, puede ver que he sobrescrito
exampleMessage
dentro de la plantilla, puede ver que funciona mientras se lee el textoHello Magento Stack Exchange
.Si elimino la anulación en el archivo de plantilla
exampleMessage
, volverá a su valor predeterminadoHello?
. Necesité eliminarvar/view_preprocessed
ypub/static/frontend
después de cambiar esto sin embargo. Supongo que Magento había almacenado en caché el valor.fuente
https://github.com/seeni9589/Magento2/tree/master/Smart/Feedback
Formulario de comentarios personalizado con el knockout js. Espero eso ayude.
fuente