Nightly custom binding handler inside the template

I created a special binding handler to render the html select component.

EG:

<select data-bind="dynamicSelect: { src: 'Category', label: 'Category'} "></select> 

After the user selects a category, the array of category fields is filled, and I attached to a div that will display a specific template

  <div data-bind="template: { name: displayMode, foreach: categoryFields }"></div> 

My templates

 <script type="text/html" id="inputTemplate"> <label data-bind="text: FieldName, attr: { for: FieldName }"></label> <input data-bind="attr: { name: FieldName, type: $parent.fieldType($data) }" /> </script> <script type="text/html" id="lookupTemplate"> <label data-bind="text: FieldName, attr: { for: FieldName }"></label> <select data-bind="dynamicSelect: { src: FieldName, label: FieldName}"></select> </script> 

Is the problem that dynamicSelect inside the template is optional? How can I reuse the binding handler inside the template?

Binding handler

 define(['durandal/composition', 'plugins/http'], function (composition, http) { composition.addBindingHandler('dynamicSelect', { init: function (element, valueAccessor) { console.log(element); console.log(valueAccessor()); var elem = $(element); elem.addClass('hidden'); elem.before('<label>' + valueAccessor().label + '</label>'); elem.after('<div><br/><label><i class="icon-spinner icon-spin active"></i> Loading...</label></div>'); console.log('/api/lookup?type=' + valueAccessor().src); return http.get('/api/lookup?type=' + valueAccessor().src).then(function (res) { var items = res.LookupItems; $.each(items, function (idx) { elem.append('<option value=' + items[idx].Id + '>' + items[idx].Name + '</option>'); }); elem.removeClass('hidden'); elem.next().addClass('hidden'); }); }, update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { } }); }); 
+4
source share
2 answers

Found my problem.

I registered a binding handler using Durandals, an auxiliary composition. Thus (and his best guess), it is called only during page creation. Explains why my first choice is populated.

I changed my binding handler to

 define(['plugins/http'], function (http) { ko.bindingHandlers.dynamicSelect = { init: function (element, valueAccessor) { var elem = $(element); elem.addClass('hidden'); elem.before('<label>' + valueAccessor().label + '</label>'); elem.after('<div><br/><label><i class="icon-spinner icon-spin active"></i> Loading...</label></div>'); console.log('/api/lookup?type=' + valueAccessor().src); return http.get('/api/lookup?type=' + valueAccessor().src).then(function (res) { var items = res.LookupItems; $.each(items, function (idx) { elem.append('<option value=' + items[idx].Id + '>' + items[idx].Name + '</option>'); }); elem.removeClass('hidden'); elem.next().addClass('hidden'); }); } }; }); 
+1
source

This will not answer your question posed by the Durandal, but it concerns your lack of thinking of MVVM in your code .: D

I would do it with ViewModel

 MyApp.LookupViewModel = function(label, src) { this.label = label; this.src = src; this.items = ko.observableArray(); this.selectedItem = ko.observable(); this.loading = ko.observable(true); this.loaded = ko.computed(function() { return !this.loading(); }, this); //simulate ajax setTimeout(function() { this.items([{ name: "Foo1", id: 1 },{ name: "Foo2", id: 2 } ]); this.loading(false); }.bind(this), 1000); }; 

If you want to use it, you simply declare a VM instance

 MyApp.ViewModel = function() { this.lookup = new MyApp.LookupViewModel("Foo", "http://foo"); } 

http://jsfiddle.net/Vjzn6/1/

My fiddle above uses a small library that takes care of finding view names, so you don't need to explicitly declare template bindings in your view.

+1
source

Source: https://habr.com/ru/post/1499093/


All Articles