Acessando dados de modelo em auxiliares

Como tudo começou

Eu queria criar um componente como um modelo em um pacote de meteoros. Como exemplo, escolhi um selecionador de data.

É bastante simples, mas para algumas coisas eu tive que pesquisar.

Para obter todas as peças necessárias, aqui está o package.js

Package.onUse(function (api) {
api
.versionsFrom('1.1.0.2');
api
.use(["templating", "underscore", "jquery", "twbs:bootstrap", "reactive-var"]);
api
.addFiles(['moment/moment.js', 'moment/fr.js', 'date-pick.html', 'date-pick.js', 'date-pick.css'], 'client');
});

Tive um problema com o pacote moment.js. É difícil adicionar localidades. É por isso que ele é adicionado como arquivos explicitamente.

Tudo está disponível no github

O complicado era acessar as variáveis ​​do template nas funções auxiliares. Sendo um selecionador de data, duas informações são necessárias para todo o modelo

  1. O mês a ser exibido
  2. A data selecionada

Na primeira versão, eu simplesmente as defini como variáveis ​​globais na parte superior do jsarquivo.

var now = new ReactiveVar();
var selectedDate = new ReactiveVar();

Isso provou ser uma má ideia, pois eles não fazem parte da instância do modelo e, portanto, se o modelo for usado duas vezes, a primeira instância não funcionará.

Então, adicionei as variáveis ​​ao dataatributo do template no createdcallback: o thisobjeto é a instância do template.

Template.datePick.created = function () {
this.data.now = new ReactiveVar(this.data.initial ? moment(this.data.initial) : moment());
this.data.selectedDate = new ReactiveVar(this.data.now.get().clone());
console
.log("template created");
}

Acessando dados de modelo em ajudantes

Mas então surgiu a questão de acessar essas variáveis ​​nos ajudantes.

Acontece que é bastante fácil, mas você precisa fazer algo especial no modelo.

Quando você usa um auxiliar fora de qualquer bloco withou each, thisé igual a . Mas se você fornecer um contexto de dados para seu ajudante, não há como acessar a propriedade de dados do modelo.templateInstance.data

exemplo 1: ajudante com contexto de dados de modelo

O primeiro elemento do modelo é a data selecionada, que, quando clicada, acionará o menu suspenso do selecionador de data

<span class="dropdown-toggle" type="button" id="datePicker" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="true">
{{selectedFormatedDate}}

</span>

O ajudante é definido assim:

selectedFormatedDate: function(){
if(this.selectedDate.get())
return this.selectedDate.get().format(this.format || "DD.MM.YYYY");
else
return "Date Picker";
}

Como você pode ver, a propriedade de dados do modelo selectedDatepode ser acessada nothis

exemplo 2: auxiliar com contexto de dados próprio

Mas isso não funciona dentro de um {{#each...

Ao listar os dias, a data selectedDatee a data exibida no momento precisam ser comparadas para saber qual célula precisa ser destacada.

Isso é feito assim:

<tbody>
{{#each weeks}}

<tr>
{{#each days}}

<td class="{{class}} {{isSelected ../..}}">{{day}}</td>
{{/each}}

</tr>
{{/each}}

</tbody>

Existem dois loops:

  1. passar por todas as semanas
  2. dentro de cada semana passe os dias

Ao exibir os dias, uma classe de destaque é adicionada ao dia selecionado. Mas como o contexto de dados é o dayobjeto da semana, não temos acesso à propriedade de dados do template.

O truque é passar a propriedade de dados do modelo como um parâmetro. Isso é feito com o ../..que diz ao Blaze para passar como parâmetro o contexto de dados dos dois níveis acima.

O auxiliar pode ser definido da seguinte forma:

isSelected: function(template){
if(this.moment){
return this.moment.isSame(template.selectedDate.get()) ? "selected-date" : "";
}
}

e o contexto de dados atual em thispode ser comparado ao contexto de dados do modelo em template.

Conclusão

Está tudo documentado, claro, mas eu ainda precisava de algum tempo para descobrir.