Meu problema:
Estou tentando escrever um pequeno aplicativo Knockout JS no Magento 2, estou tendo dificuldades para inicializar o aplicativo, pois quando o uso ko.applyBindings(AppViewModel, document.getElementById("koTest"));
quebra o Knockout usado pelo Magento e gera este erro:
Uncaught Error: You cannot apply bindings multiple times to the same element.
Eu suspeito que é por causa de:
Eu suspeito que isso ocorre porque o Magento 2 já usa ko.applyBindings()
dentro app/code/Magento/Ui/view/base/web/js/lib/knockout/bootstrap.js
. E como isso não especifica um nó, não posso usar ko.applyBindings
novamente.
Se eu não usar ko.applyBindings(AppViewModel, document.getElementById("koTest"))
no meu código, meu aplicativo não será inicializado.
Isso me faz pensar que, de alguma forma, preciso usar o ko.applyBindings()
arquivo in knockout / bootstrap.js, mas não sei como, alguém pode ajudar? Tenho pouca experiência com o Knockout.
My Code
<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>
fonte
Respostas:
Método simples em que você NÃO precisa usar modelos html
Graças a Vinai Kopp, finalmente consegui uma resposta para isso, é muito mais simples do que minha solução hacky anterior (eu estava limpando nós). Tudo que você precisa fazer é definir
'ko'
como uma dependência e adicionar seu código dentro de uma função de retorno.Abaixo está um exemplo simples que renderiza algum texto transmitido via JSON.
app/code/VENODR/MODULE/view/frontend/templates/knockout-example.phtml
Aqui, informamos ao Magento o escopo de nossos componentes (isso deve corresponder
data-bind: "scope: 'example-scope'"
e passar dados adicionais. Esse pode ser o URL base, uma mensagem simples, praticamente o que você desejar. Passei uma string (eco do PHP) como exemploE aqui escrevemos nosso Javascript.
app/code/VENDOR/MODULE/view/frontend/web/js/knockout-example.js
Resultado
---------------------
Método em que você precisa usar modelos HTML
Se você deseja usar o sistema de modelos HTML no Magento2 / Knockout (que eu presumo que você precisará para trabalhos significativos), existem algumas mudanças que você precisará fazer em comparação com a minha resposta simplificada (abaixo).
Se você não precisar da funcionalidade do modelo, role para baixo até a minha antiga resposta simplificada.
Os arquivos que estou usando para este exemplo são:
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
O arquivo de modelo PHTML
A única alteração no nosso modelo PHTML é a chamada para a
getTemplate()
função:O arquivo JS (componente)
Existem algumas alterações que você precisará fazer no arquivo JS, que serão detalhadas abaixo.
1 - Sua função de retorno agora precisa estender o módulo uiComponent:
2 - Você precisa adicionar uma
initialize
função e chamadathis._super()
.this._super()
chamará a função do componente pai com o mesmo nome. Então, neste caso eu acho que ele irá chamarinitialize
deuiComponent
.3 - Opcional - Você também pode definir alguns padrões para o seu componente aqui, acho que é uma boa prática a seguir, pois facilita o trabalho com o seu componente. Ao reutilizá-lo, você pode manter os padrões ou, se desejar personalizá-lo, pode chamá-lo com novos argumentos sem alterar o componente.
Por exemplo, se você observar os padrões no JS, ele define
exampleMessage
como'Hello?'
ainda a página está renderizando o texto comoHello Magento Stack Exchange!
. Isso ocorre porque eu substituíexampleMessage
o arquivo PHTML quando chamei o componente.O modelo HTML
Ainda estou procurando e vendo do que os modelos HTML são capazes, presumo que os recursos mencionados na documentação do Knockout JS possam ser usados aqui, tornando-os bastante flexíveis.
Acabei de adicionar um texto de lorem ipsum por enquanto, provavelmente fornecerei outra pergunta / resposta depois de descobrir o que os modelos HTML podem fazer.
O resultado e substituindo os padrões
Como mencionado anteriormente, você pode ver que eu sobrescrevi
exampleMessage
no modelo, você pode vê-lo funcionando enquanto o texto é lidoHello Magento Stack Exchange
.Se eu remover a substituição no arquivo de modelo,
exampleMessage
ela retornará ao padrãoHello?
. Eu precisava excluirvar/view_preprocessed
epub/static/frontend
depois de alterar isso. Presumo que Magento tenha armazenado em cache o valor.fonte
https://github.com/seeni9589/Magento2/tree/master/Smart/Feedback
Formulário de feedback personalizado com o nocaute js. Espero que ajude.
fonte