2012-01-09 12 views
7

mam natknąć kilka sytuacji, w których muszę zakodować moje wezwanie szablonu tak:Rozszerzone składni dla przekazywania parametrów do KnockoutJS szablonów

<!-- ko template: {name: 'paginatedList', 
        data: {listContainer: paginatedResults, itemTemplate: $parent.template}} --> 
<!-- /ko --> 

ponieważ oprócz mojego obiektu danych (np paginatedResults), I trzeba podać dodatkowe informacje, takie jak nazwa szablonu, który ma być używany do renderowania elementów. Jako inny przykład, podczas renderowania elementu na liście, może potrzebować znać bieżące ustawienia filtru, który jest przechowywany w jakimś kontekście w sposób logicznie daleki od pozycji na liście.

Zamiast wykrzywiać mój model danych (w powyższym przykładzie, zastępując paginatedResults z {listContainer: paginatedResults, itemTemplate: $parent.template}}, byłoby miło mieć trochę składnię szablonów, które pozwala mi przejść dookoła (i acccrue jako szablony oceniane są hierarchicznie) jakiś dodatkowy kontekst, że głęboko zagnieżdżony szablon może potrzebować podczas renderowania siebie.

myślę, co mi zastanawiać się wykonalność dodając dodatkowy (opcjonalny) parametr do ko.bindingHandlers funkcji (init i update) aby wyglądały jak to:

function (element, 
      valueAccessor, 
      allBindingsAccessor, 
      viewModel, 
      bindingContext, 
      context) 

Podczas kodowania powyższy przykład, że powinienem być w stanie powiedzieć coś

<!-- ko template: {name: 'paginatedList', 
        data: paginatedResults, 
        context: {itemTemplate: $parent.template}} --> 
<!-- /ko --> 

albo jeszcze lepiej,

<!-- ko template: {name: 'paginatedList', 
        data: paginatedResults, 
        itemTemplate: $parent.template} --> 
<!-- /ko --> 

i mają itemTemplate stać zmienna mogę zapoznać się w zagnieżdżonych szablonów i data-bind atrybuty.

Czy to ma sens? Nie mam pojęcia, jak trudno byłoby to zrealizować. Sądzę, że trzeba się martwić kolizjami nazw, ale niektóre konwencje nazewnictwa mogą je omijać.

Gene

Odpowiedz

9

Bez zmian nokaut rdzeń, myślę, że najlepsze, co można zrobić, to owinięcie wiążący, który tworzy strukturę podobną do tego, co obecnie przechodzą.

Oprawa może wyglądać następująco:

ko.bindingHandlers.templateWithContext = { 
    init: ko.bindingHandlers.template.init, 
    update: function(element, valueAccessor, allBindings, data, context) { 
     var options = ko.utils.unwrapObservable(valueAccessor()); 

     ko.utils.extend(context, options.context); 

     return ko.bindingHandlers.template.update.apply(this, arguments); 
    } 
}; 

nazwałbyś to podoba:

<div data-bind="templateWithContext: { name: 'itemsTmpl', data: items, context: { title: 'First' } }"></div> 

Oto przykład: http://jsfiddle.net/rniemeyer/QNvFn/

Wygląda używasz natywnych szablonów, ale jeśli w dalszym ciągu korzystasz z szablonów jQuery, to znaczy, że zawiera on templateOptionsfeature, który używał funkcjijQuery Templates przekazywać dane kontekstowe. To nie jest dostępne w szablonach natywnych. Ogólna rekomendacja polega teraz na użyciu $root, $parent i $parentsvariables w celu uzyskania dostępu do informacji lub przekazania obiektu w sposób opisany w twoim poście jako data.

+0

Dzięki! Zgadzam się, że to jest właściwe, ale nie wystarcza, aby zagwarantować dodatkowy wiążący przewodnik. Byłoby ciekawie zobaczyć, jak często ten wzorzec pojawia się w złożonych aplikacjach. –

+0

Dzięki temu bardzo mi pomaga.Jeśli napiszę opakowanie szablonu, czy mogę ustawić nazwę szablonu wewnątrz 'init'? – tbruyelle

+0

@tbruyelle - zdecydowanie możesz ustawić nazwę. Pomysł polegałby na tym, że wewnątrz wiązania opakowania tworzysz opcje, które chcesz przekazać do rzeczywistego powiązania szablonu. Oto przykład, który może jest nieco bardziej ogólny niż potrzebujesz (możesz po prostu ustawić nazwę na obiekcie valueAccessor()): http://jsfiddle.net/rniemeyer/7rcFD/ –

Powiązane problemy