Access polymer component properties from callback? - javascript

With this polymer element definition:
<script>
Polymer({
is: 'hello-world',
properties: {
dataId: {
type: String
},
value: {
type: String
}
},
ready: function() {
console.log(this.dataId);
registerCallback(this.dataId, function (data) {
var z = data.someValue;
this.value = z;
});
}
});
</script>
When it tries to set this.value, this is actually the data, not the element. I want it to set the polymer property "value" to the value of z. How can I do this?
Here is the registerCallback() if needed:
function registerCallback(id, callback) {
callbackMap[id] = callback;
}

There are two ways of doing it
As you already know this has a different meaning inside the callback so one way would be to store this(Polymer element) inside some other variable
var self=this;
registerCallback(function(){
self.data = some value
})
Second option is to bind this with your callback
registerCallback(function(){
this.data= some value
}.bind(this));

Related

In Object refer to itself anonymous function key Javascript

I have this object:
var crudConfig = function($wizard, $formModal, $deleteModal) {
'use strict';
return {
handleOnShowFormModal : function() {
$formModal.on('show.bs.modal', function(event) {
...................
this.fillForms(data);
....................
});
return this;
},
fillForms : function(data) {
//do stuff
return this;
}
}
}
The problem appears when I call the fillForms with the param.
Uncaught TypeError: this.fillForms is not a function
As the fillForms key is an anonymous function how can I call it from inside the object? On other relative questions I only found how to refer itself if the key has a string value and the I call like this: this.fillForms .
this within the callback references the $formModal element. What you need to do is store this that refer to the object in a variable before the event listener is called and use the variable within the callback to access the object.
Just like this:
handleOnShowFormModal : function() {
var _this = this
$formModal.on('show.bs.modal', function(event) {
_this.fillForms(data);
});
return this;
},

backbone marionette pass variable to view method

I have simple situation and can't understand why variable that I pass to function always undefined.
var ProjectItemView = Backbone.Marionette.ItemView.extend({
template: "#ProjectItemTemplate",
initialize: function () {
var id = this.model.get('project_id');
$.getJSON('service/api.php/projects/' + id + '/progress').done(function (data) {
this.renderProgress('4'); //<== pass here
});
},
renderProgress: function (why) {
alert(why); //<== undefined
...
},
...
});
I expect that it equals '4'. In next step I want to pass "data" but now I realize that I can't pass anything.
Since you're invoking renderProgress on the return of $.getJSON you can simply provide the function reference to the done()method of the returned jQuery Promise. Your code would look like this:
var ProjectItemView = Backbone.Marionette.ItemView.extend({
template: "#ProjectItemTemplate",
initialize: function () {
var id = this.model.get('project_id');
$.getJSON('service/api.php/projects/' + id + '/progress')
.done(this.renderProgress);
},
renderProgress: function (data) {
alert(data);
...
},
...
});
If you'll need the view context inside renderProgress (like, for example, to refer to a view property), then provide done() a version of renderProgress that's bound to the view context:
$.getJSON('service/api.php/projects/' + id + '/progress')
.done(_.bind(this.renderProgress, this));
where _.bind is an UnderscoreJS function. Read more about it here.
You loose the context in $.getJSON done callback. Try this:
var ProjectItemView = Backbone.Marionette.ItemView.extend({
template: "#ProjectItemTemplate",
initialize: function () {
var id = this.model.get('project_id');
var _this = this;
$.getJSON('service/api.php/projects/' + id + '/progress').done(function (data) {
_this.renderProgress('4'); //<== pass here
});
},
renderProgress: function (why) {
alert(why); //<== undefined
...
},
...
});
You don't have access to this inside " $.getJSON( " assign this to any variable and then call "renderProgress" method.
var currentObj = this;
$.getJSON('service/api.php/projects/' + id + '/progress').done(function (data) {
currentObj .renderProgress('4'); //<== pass here
});
because in your case this points to current object of that function and not to view object.

Passing variable into object method javascript

trying to get my head around objects, methods, closures, etc... in Javascript.
Can't see why this isn't working, some fundamental flaw in my thinking I guess. I'm expecting the val variable to be passed through to the addNote() function but it isn't. I thought that any variables declared outside of a function are available to that function, as long as they're not within another function. Is that not correct?
if(typeof(Storage) !== "undefined") {
console.log(localStorage);
var $input = $('#input'),
$submit = $('#submit'),
$list = $('#list'),
val = $input.val();
var noteApp = {
addNote : function(val) {
var item = val.wrap('<li />');
item.appendTo($list);
clearField();
},
clearField : function() {
$input.val = '';
},
delNote : function(note) {
}
};
$submit.on('click', function(){
noteApp.addNote();
});
} else {
}
I'm trying to learn how the pros manage to get their code so clean, concise and modular. I figured a note app would be a perfect start, shame I got stuck at the first hurdle...
Cheers.
There are several issues with the code in the question
defining an argument named val and not passing an argument to the function
when calling clearField() inside the object literal it's this.clearField()
You're only getting the value once, not on every click
val is a string, it has no wrap method
$input.val = ''; is not valid jQuery
I would clean it up like this
var noteApp = {
init: function() {
if (this.hasStorage) {
this.elements().events();
}
},
elements: function() {
this.input = $('#input');
this.submit = $('#submit');
this.list = $('#list');
return this;
},
events: function() {
var self = this;
this.submit.on('click', function(){
self.addNote();
});
},
hasStorage: (function() {
return typeof(Storage) !== "undefined";
})(),
addNote: function() {
this.list.append('<li>' + this.input.val() + '</li>');
this.clearField();
return this;
},
clearField: function() {
this.input.val('');
},
delNote : function(note) {
}
}
FIDDLE
Remember to call the init method
$(function() { noteApp.init(); });
In your call to addNote(), you don't pass any argument for the val, so it will be undefined:
noteApp.addNote();
// ^^ nothing
Pass the input (seems you want the jQuery object not the string value because of your val.wrap call):
noteApp.addNote($input);
When you declare the val in the function, it is scoped to that function and will only be populated if the function call passes a value for that argument. Even if you have another variable in an upper scope with the same name val, they are still differentiated. Any reference to val in the function will refer to the local val not the upper scope.

knockout pass additional parameters to subscription function

What I want to achieve is to create subscription for model properties. This subscription function should call WebApi via Ajax updating property value in database. For ajax call I need three paramaters: "fieldName", "fieldValue" and "modelId", ajax will update database row based on those three parameters.
I have many properties and all of them need the same functionality, so I do not want to subscribe for each property individually, so I found a following suggestion:
ko.subscribable.fn.withUpdater = function (handler) {
var self = this;
this.subscribe(handler);
//support chaining
return this;
};
Add this is how it is "attached" to observables:
self.ModelId= ko.observable();
self.CompanyName = ko.observable().withUpdater(update);
where update is some js function outside model.
However, I have problem, because I am not able to pass three paramaters to update functions (or also I can say in another words - I need to be able to get viewModel.ModelId property value inside update, as well as propertyName).
function update (propertyName, propertyNewValue, anotherPropertyValue) {
//do ajax update
}
As an example for CompanyName property it will be:
update("CompanyName", "New Company value here", 3),
where
3 == viewModel.ModelId
There might be a better way to do this, but the following will work:
First, add a target object to the withUpdate method:
ko.subscribable.fn.withUpdater = function (handler, target, propname) {
var self = this;
var _oldValue;
this.subscribe(function (oldValue) {
_oldValue = oldValue;
}, null, 'beforeChange');
this.subscribe(function (newValue) {
handler.call(target, _oldValue, newValue, propname);
});
return this;
};
The update subscribe function will get scoped to the target property:
var update = function (propertyName) {
console.log('propname is '+ propname + ' old val: ' + oldvalue + ', new val: ' + newvalue + ', model id: ' + this.ModelId());
}
Now you will need to use it a little differently.
self.CompanyName = ko.observable().withUpdater(update, self, "CompanyName");
An example http://plnkr.co/edit/HhbKEm?p=preview
I couldn't get the scope of the withUpdater function to be that of the object without explicitly passing in the target and a string for the company name.
You can declare your function as a variable outside of the 'fn' scope.
var dataservice = 'my class that has the data calls';
var altFunc = function () {
return ko.pureComputed(function () {
var currentItem = this().filter(function (item) {
// Do knockout stuff here and return your data
// also make calls to the dataservice class
}, this, dataservice);
};
ko.observableArray.fn.someNewFunctionality = altFunc;

JQuery Knockout ComputedObservable Write not getting called for ObservableArray

I am trying to bind a computed observable which internally uses a observable array.
The "read" method does get called while loading.
But the "write" method does not get called when the values in the table are changed and the focus is moved.
Note that for simple computed observables , which do not wrap a array but a simple string, the "write" method works. However for this scenario it does not work.
I looked on the Knockout api documentation and in online forums but could not find anything about this. Can someone please advice?
Following is the HTML code
<thead>
<tr><th>People Upper Case Name</th></tr>
</thead>
<tbody data-bind="foreach: uppercasepeople">
<tr>
<td ><input type="text" data-bind="value: name"/></td>
</tr>
</tbody>
</table>
Following is the Java Script code
<script type="text/javascript">
var MyViewModel = function () {
var self = this;
var self = this;
//Original observable array is in lower case
self.lowercasepeople = ko.observableArray([
{ name: "bert" },
{ name: "charles" },
{ name: "denise" }
]);
//coputed array is upper case which is data-bound to the ui
this.uppercasepeople = ko.computed({
read: function () {
alert('read does get called :)...yaaaa!!!');
return self.lowercasepeople().map(function (element) {
var o = { name: element.name.toUpperCase() };
return o;
});
},
write: function (value) {
alert('Write does not get called :(... why?????');
//do something with the value
self.lowercasepeople(value.map(function (element) { return element.toLowerCase(); }));
},
owner: self
});
}
ko.applyBindings(new MyViewModel());
I have put the code similar to an example shown on the Knockout API documentation so people easily relate.
The computed observable that you have only deals with the array itself. The write function would only get called if you tried to set the value of uppercasepeople directly.
In this case, you would likely want to use a writeable computed on the person object itself and make the name observable. The writeable computed would then convert the name to upper-case and when written would populate the name observable with the lower-case value.
var MyViewModel = function () {
var self = this;
//Original observable array is in lower case
self.lowercasepeople = ko.observableArray([
{ name: "bert" },
{ name: "charles" },
{ name: "denise" }
]);
self.recententlyChangedValue = ko.observable();
//coputed array is upper case which is data-bound to the ui
this.uppercasepeople = ko.computed({
read: function () {
alert('read does get called :)...yaaaa!!!');
return self.lowercasepeople().map(function (element) {
var o = { name: element.name.toUpperCase() };
return o;
});
},
write: function (value) {
alert('It will be called only when you change the value of uppercasepeople field');
//do something with the value
self.recententlyChangedValue(value);
},
owner: self
});
}

Categories