Como inicializar o ViewModel da página (parcial) no Durandal/ASP.NET MVC?
-
21-12-2019 - |
Pergunta
eu tenho esta abordagem (gerando arquivos html a partir de cshtml).
E Estrutura de diretório padrão do Durandal (nada especial).
Em algumas de minhas páginas (parcial) Tenho o seguinte (entre outros) (SubPage1.cshtml (referenciado como 'SubPage1.html' em durandal)):
...
<select data-bind="event: { change: doSomething }, value: facilityId">
<option value="0">Any Facility</option>
@foreach (var facility in Data.CurrentUserFacilities())
{
<option value="@facility.FacilityId" selected="@CertainCondition">@facility.FacilityName</option>
}
</select>
...
(facilityId
é ko.observable()
no meu código ViewModel)
Eu preencho dados dependendo da sessão do usuário atual.Isso é muito conveniente a ver com Navalha.Nesse caso, não preciso que os dados do menu suspenso sejam apresentados no ViewModel do meu Durandal (quero dizer, a lista inteira).No entanto, eu precisa que o valor selecionado do menu suspenso seja aplicado ao ViewModel (SubPage1.js) da página (quando a página é carregada).
Qual é a melhor maneira (e se houver) de lidar com esta situação?Eu certamente entendo que, idealmente, eu deveria carregar a página como estática (apenas com ligações Knockout), fazer alguma solicitação ajax ao servidor e vincular os dados carregados.Mas, a) usar a sintaxe do Razor é muito mais conveniente e limpo;b) que envolve solicitação adicional de ajax (e lógica de servidor adicional).
Outra abordagem que vejo é notificar o ViewModel sobre a página ser carregada de alguma forma e definir (provavelmente, manualmente via javascript) o valor atual do facilitiesId.Como <script type='text/javascript'> myViewModelIgetSomehow.facilityId(45); </script>
.Mas essa também não parece ser a melhor abordagem.
Alguma opinião sobre isso?
Na verdade, essa é uma questão de como lidar com o último pensamento mencionado (como passar alguns valores da página carregada SubPage1.cshtml para ViewModel SubPage1.js) não apenas como lidar com o Razor + Durandal ViewModel.
Obrigado!
Solução
Acho que sua melhor opção seria criar uma ligação personalizada para nocaute.Aqui está um exemplo simples:
ko.bindingHandlers["serverCombo"] = {
init: function (element, valueAccessor) {
var $element = $(element);
var options = ko.unwrap(valueAccessor());
var observableTarget = options.value;
$element.change(function onElementChanged() {
var newValue = $element.val();
observableTarget(newValue);
});
},
update: function (element, valueAccessor) {
var $element = $(element);
var options = ko.unwrap(valueAccessor());
var observableTarget = options.value;
$element.val(observableTarget());
}
}
Você poderia então usar essa ligação da seguinte maneira:
<select data-bind="serverCombo: { value: facilityId }">
<option value="1">The Deck</option>
<option value="2">The Pool</option>
<option value="3">The Shagpile Carpet and Mirrored Ceiling room</option>
</select>
Aqui está um violino que junta tudo.Espero que ajude!