i am using http://aehlke.github.com/tag-it/ in my code how to bind with viewmodel
html
<ul data-bind='jqueryui: "tagit",foreach: Tags' >
<li class="tagit-choice ui-widget-content ui-state-default ui-corner-all" data-bind='with: $data'>
<span class="tagit-label" data-bind='text: $data'></span>
<a class="tagit-close">
<span class="text-icon">×</span>
<span class="ui-icon ui-icon-close"></span>
</a>
<input type="hidden" name="item[tags][]" data-bind='value: $data' style="display: none;">
</li>
</ul>
Js code
function AppViewModel() {
var self = this;
function Tag(data) {
this.Name = data;
}
self.Tags = ko.observableArray([
new Tag('red'),
new Tag('blue'),
new Tag('green')
]);
}
// Activates knockout.js
ko.applyBindings(new AppViewModel());
Thanks in advance for your assistance!
Here's a another binding handler for knockout based on Robert Wagner's answer, since i didnt feel that it was dynamic enough:
ko.bindingHandlers.tagit = {
//https://github.com/aehlke/tag-it
init: function (element, valueAccessor, allBindingsAccessor) {
var bind = function () {
valueAccessor().tags($(element).tagit("assignedTags"));
};
var options = $.extend({
allowSpaces: false,
caseSensitive: false,
showAutocompleteOnFocus: true,
afterTagAdded: function(t,s) { bind(); },
afterTagRemoved: function(t,s) { bind(); },
placeholderText: "",
preprocessTag: function () { },
beforeTagAdded: function (evt, tag) {
if (tag.tagLabel.length == 0 || tag.tagLabel.toLowerCase() === options.placeholderText.toLowerCase()) {
return false;
}
return true;
}
}, valueAccessor().options || {});
var tags = valueAccessor()["autocomplete"];
if (tags)
$.extend(options, {
autocomplete: $.extend({ source: tags.source, delay: 0, minLength: 0 },tags)
});
$(element).tagit(options);
},
update: function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
var tags = value.tags();
$(element).tagit("removeAll");
for (var x = 0; x < tags.length; x++) {
$(element).tagit("createTag", tags[x]);
}
}
};
My preprocess and autocompleter functions:
self.TagAutocompleter = function (d, ds) {
DataMethod.postData("tag/autocomplete", d, function (data) {
ds(ko.utils.arrayMap(data, function (t) { return t.Tag; }));
});
};
self.TagProcessor = function (tag) {
return tag.toLowerCase().replace("#", '');
};
And use in html:
<ul data-bind="tagit:{tags:Tags, autocomplete:{source:TagAutocompleter, delay:250, minLength: 2}, options:{preprocessTag: TagProcessor}}">
</ul>
Here is a custom binding https://gist.github.com/droyad/6136446
ko.bindingHandlers.tags = {
init: function (element, valueAccessor, allBindingsAccessor) {
var bind = function() {
var observable = valueAccessor();
observable($(element).tagit("assignedTags").join(','));
};
var options = {
allowSpaces: true,
caseSensitive: false,
showAutocompleteOnFocus: true,
afterTagAdded: bind,
afterTagRemoved: bind
};
var tags = allBindingsAccessor()["tagsSource"];
if (tags)
$.extend(options, {
autocomplete: { source: tags, delay: 0, minLength: 0 }
});
$(element).tagit(options);
$(element).data('uiTagit').tagInput.css("width", "50px");
},
update: function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
var tags = value.split(',');
$(element).tagit("removeAll");
for (var x = 0; x < tags.length; x++) {
$(element).tagit("createTag", tags[x]);
}
}
}
I write a simple fiddle where it's work. It's construct component with de tag list. Fiddle
But it's not a two ways binding. If you wan't to do that i advise you to create a custom binder where it call the knockout's foreach model binder . See information to Custom model binders
On the init function, you need to subscibe to tags changes in knockout observableArray for update the control. And you need to subscribe to onTagAdded event and onTagRemoved event.
There is a sample code where i extend the foreach component:
ko.bindingHandlers.extendForeach = {
makeForeachValueAccessor: function (valueAccessor) {
return function () {
if ((!bindingValue) || typeof bindingValue.length == "number"){
bindingValue = {
data : bindingValue
}
}
return {
'data': bindingValue['data'],
'afterAdd': bindingValue['afterAdd'],
'beforeRemove': bindingValue['beforeRemove'],
'afterRender': bindingValue['afterRender'],
};
};
},
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var newValAccess = ko.bindingHandlers.extendForeach.makeForeachValueAccessor(valueAccessor);
return ko.bindingHandlers.foreach.init(element, newValAccess, allBindingsAccessor, viewModel, bindingContext);
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var newValAccess = ko.bindingHandlers.extendForeach.makeForeachValueAccessor(valueAccessor);
return ko.bindingHandlers.foreach.update(element, newValAccess, allBindingsAccessor, viewModel, bindingContext);
}
}
I hope this help you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With