I'm having a problem to use ko.mapping.fromJS( in knockout. I've been testing on version 2.2 and 3.
Anybody else who has had problems? Or are there any other alternatives to updating a instatieted viewmodel?
if (PAGE.blogViewModel == null) {
PAGE.blogViewModel = new BlogViewModel(data);
ko.applyBindings(PAGE.blogViewModel, document.getElementById("blog_container"));
} else {
ko.fromJSON(data, PAGE.blogViewModel);
}
The updating ko.fromJSON(data, PAGE.blogViewModel); does not work.
*TypeError: ko.fromJSON is not a function*
And oddly enough I've used ko.mapping.fromJS( before and it has worked.
ko.mapping.fromJS(data, PAGE.blogViewModel);
TypeError: ko.mapping is undefined
ko.mapping.fromJS is not deprecated because it was never part of the core Knockout library.
The ko.mapping.fromJS is comming from the Knockout Mapping plugin.
You need to download and include it separately in your HTML to use it.
It sounds like you haven't included the ko.mappings-library. Make sure that it is loaded after Knockout is loaded.
Related
I'm trying to build a new conditional helper for my Ember application.
Is important mention that I'm using Ember 1.10.1 that uses Handlebars 2.0 and I can't upgrade it, would be great solving the problem with this version of Ember.
Before writing here I tried different solutions and debugged the Ember code a lot, I'm near to the solution but probably I'm missing something.
First of all, I tried with the following approach reading the Handlebar documentation:
Ember.Handlebars.registerHelper('helperName', function(conditional, options) {
if(conditional) {
return options.fn(this);
} else {
return options.inverse(this);
}
});
And here the template:
{{#helperName booleanCondition}}
print true
{{else}}
print false
{{/helperName}}
Everything worked fine calling the fn function but the inversion function (used to render the template of the else branch) was actually an object instead of a function.
Then I started debugging the Ember code and I tried to follow the same approach that Ember uses with the if helper, so I ended up with the following:
Ember.Handlebars.registerHelper('helperName', function(condition, options) {
var permission = Ember.Object.extend({
can: Ember.computed(function() {
return condition;
})
}).create();
Ember.Handlebars.helpers.boundIf.helperFunction.call(this, ["can"], permission, options, options.data.buffer);
});
can is the property bound to the if, used to change the template if the property changes, since we are using the boundIf version of the if (that does what I just said).
The problem of this solution, that imho could be the nearest to be correct, is that the property is not computed correctly and the helper prints always the false value.
I debugged really a lot without making it working, so any help would be very appreciated and I hope this could be useful for someone else as well.
If what you're trying to do is build a conditional approach that supports authorization questions, you should take a look at ember-can. It is an Ember-CLI addon (whereas it looks like you are doing globals) but older versions worked with Ember 1.10. You should be able to reference what they do there and pull it in on your setup
The good news is you are on Ember 1.10!
This means you have subexpressions. And its simple to create a bound non-block helper:
Ember.HTMLBars._registerHelper('foo', function(bar) {
return bar == 'bar';
});
To use it as a block helper combine it with the {{#if}} helper:
{{#if (foo model)}}
in if
{{else}}
in else
{{/if}}
I've been attempting to implement a ASP.NET MVC custom validation method. Tutorials I've used such as codeproject explain that you add data-val-customname to the element. Then jQuery.validate.unobtrusive.js then uses the third segment of the attribute
data-val-<customname>
as the name of the rule, as shown below.
$.validator.addMethod('customname', function(value, element, param) {
//... return true or false
});
However I just can't get the customname method to fire. By playing around I have been able to get the below code to work, but according to all the sources I've read Unobtrusive validation should not work like this.
$.validator.addMethod('data-val-customname', function(value, element, param) {
//... return true or false
});
I've posted an example of both methods
jsfiddle example
Any help would be much appreciated
I've updated my question hopefully to make clearer.
I have finally found got there in the end, but still feels like too much hard work and therefore I've probably got something wrong. Initial I was scuppered by a bug in Chrome Canary 62 which refused to allow the adding of a custom method.
My next issue was having to load jQuery, jQuery.validate and jQuery.validate.unobtrusive in the markup and then isolate javascript implementation in a ES6 class. I didn't want to add my adaptors before $().ready() because of my class structure and loading of the app file independent of jQuery. So I had to force $.validator.unobtrusive.parse(document);.
Despite this I was still having issues and finally debugged the source code and found that an existing validator information that is attached to the form was not merging with the updated parsed rules, and essentially ignoring any new adaptors added.
My final work around and admit feels like I've done too much, was to destroy the initial validation information before my forced re-parse.
Here is the working jsfiddle demo
Here is some simplified code
onJQueryReady() {
let formValidator = $.data(document.querySelector('form'), "validator" );
formValidator.destroy();
$.validator.unobtrusive.adapters.add("telephone", [], function (options) {
options.rules['telephone'] = {};
options.messages['telephone'] = options.message;
});
$.validator.unobtrusive.parse(document);
$.validator.addMethod("telephone", this.handleValidateTelephoneNumber);
}
We've been using the Typeahead.js library in our Ember app (via this addon) with success on Ember versions prior to 1.10, but the upgrade to Ember 1.10 is causing us problems.
Until now we've had success compiling templates that are passed into the typeahead component and passing that along to the typeahead library like this:
templates: {
// this.get('suggestionTemplate') is a string of handlebars template
suggestion: Handlebars.compile(this.get('suggestionTemplate')),
<other code>
}
This does not work in Ember 1.10, however, as typeahead.js throws the below error when executing this line of code:
Code:
$el = $(html.suggestion).append(that.templates.suggestion(suggestion)).data(datasetKey, that.name).data(valueKey, that.displayFn(suggestion)).data(datumKey, suggestion);
Error:
Uncaught TypeError: that.templates.suggestion is not a function
Previously that.templates.suggestion, which is the value from the first code block above, was a function that could be passed the object suggestion and it would compile the actual template. With HTMLBars, that.templates.suggestion is no longer a function but rather is an HTMLBars object, so this code no longer works.
Is there a better way to do this same thing in Ember 1.10 that will match the previous behavior?
I remember I had a similar problem using Handlebars.compile I ended up opting for passing a function to suggestion instead, and then the template content:
templates: {
empty: '<span>No results</span>',
suggestion: function(item){
return '<div>' + item.name + '</div>';
}
}
Hope this works for you too.
If such add-on is no longer being maintained I'd suggest you to use typeahead straight (no cli add-on), I've been using it like this since Ember 1.7 and now I'm on 1.11
In the end we just kept a separate handlebars dependency in our bower.json since it seems like the typeahead library requires you to pass in vanilla handlebars templates to it
I'm playing around with Knockout and now trying to use the Knockout address plugin (based on jQuery address).
This code below works, except that when I try entering the address the linkObservableToUrl provides the page is loaded without the right tags. I guess something is wrong in the way I'm loading the messages, but I'm not sure how this should be done using the Knockout framework.
I've got the following code, which is causing an infinite loop:
var viewModel = {
page: ko.observable(1),
//messages: ko.observableArray([]),
tags: ko.observable()
};
viewModel.filterTags = function (filterTags) {
viewModel.tags(filterTags);
};
viewModel.messages = ko.dependentObservable(function () {
$.ajax(
// abbreviated
data: ko.toJSON(viewModel),
// abbreviated
)}, viewModel);
ko.applyBindings(viewModel);
ko.linkObservableToUrl(viewModel.tags, "tags", null);
How can I solve this and still have the messages depend on page and tags?
Switch to AngularJS. Angular's databinding is much better than Knockout's. Much of the problems you are encountering here with infinite loops, etc. are due to Knockout's need for observable wrappers.
Angular does not require observable wrappers of your objects. Angular can observe any standard JSON/Javascript object, and databind directly to any HTML element via MVVM.
In Angular, you would simply make your AJAX call for ViewModel.messages, and the standard JSON would be applied to your ViewModel.messages property. No observable wrappers. This eliminates the need for ko.dependentObservable() and thus - removes your infinite loop.
http://www.angularjs.org
In the second example (which is quit long for a code snippet) you have this:
viewModel.messages = ko.dependentObservable(function () {
...
data: ko.toJSON(viewModel),
...
If the call to ko.toJSON tries to get the value of all the observable properties on the view model, it will try to evaluate the viewModel.messages property. That will call ko.toJSON again, leading to an infinite loop.
I'm using Uploadify to upload file in my CMS. Everything works fine until recently. I got an error
Error calling method on NPObject
on this line
document.getElementById(jQuery(this).attr('id') + 'Uploader').startFileUpload(ID, checkComplete);
on this part
uploadifyUpload:function(ID,checkComplete) {
jQuery(this).each(function() {
if (!checkComplete) checkComplete = false;
document.getElementById(jQuery(this).attr('id') + 'Uploader').startFileUpload(ID, checkComplete);
});
},
I don't know why and after a day debugging and testing I found that if I remove replace(/\&/g, '\\&') from
String.prototype.escAll = function(){
var s = this;
return s.replace(/\./g, '\\.').replace(/\?/g, '\\?').replace(/\&/g, '\\&');
};
It then works again. I really don't know why.
Any helps would be appreciated!
I think the reason is in additional Javascript libraries you use.
Some libraries (for example Prototype.js or jQuery.js) change behaviour of your code. For example, you can't overload prototype in some cases. The result may be undefined in clear (obvious) places (like you use an array variable with wrong index). You should view the source code of additional libraries, probably they do with prototype something that breaks your code in the function you mentioned.
In my practice I had the situation when overloading of prototype worked incorrectly (it was String prototype like in your case).
So just don't use prototype.