I have an external object doing a lot of processing outside my view model. I want to be able to send data from this object using a trigger.
Is it possible to pass data to a subscriber from a plain object using valueHasMutated ?
function obj(trigger) {
var self = this;
self.notify = function (value) {
trigger.call(undefined,value);
};
}
function vm() {
var self = this;
self.flag = ko.observable();
self.myobj = new obj(self.flag.valueHasMutated);
self.flag.subscribe(function(value) {
console.debug("Caught trigger with value " + value);
});
}
ko.applyBindings(new vm());
// trigger
ko.dataFor(document.body).myobj.notify("Working");
The trigger is poping but the value i'm getting is undefined.
I set up an example on JSBIN here
Appreciate any help with this.
EDIT
Looking at the source i can see that valueHasMutated gets the "new value" but still cant make it work.
OK, posting answer, change the value of flag directly: self.myobj = new obj(self.flag)
Related
Here I have define self.fromDate = ko.observable() and self.toDate = ko.observable() now this value is set when click event of button in function is call with ajax request. On success ajax call need to set values to these two view model. And set value must be accessible outside of ajax success function as well
var app = function(){
self.fromDate = ko.observable();
self.toDate = ko.observable();
self.setThisYear = function(){
$.getJSON("/Dashboard/GetFiscalYearDetails", function (data) {
self.fromDate(data.fromDate);
self.toDate(data.toDate);
console.log(self.fromDate()); //set data
console.log(self.toDate()); //set date
}
console.log(self.fromDate()); //undefined
console.log(self.toDate()); //undefined
}
}
ko.applyBindings(new app());
This Year
This maybe wrong but it looks you are just missing one essential thing:
defining self
var app = function(){
var self = this;
...
also there is syntax errors like $.getJSON( never gets closed
you should use the browser console to determine errors, also you can assign the vm to a variable itself, like:
var system = ko.applyBindings(new app());
in console or any followed scripts you could then just type
system.fromDate()
to retrieve the current observable value, or:
system.fromDate("123")
to set the value
I'm quite new to Angular and am trying to understand how everything works. I've been poking around and couldn't find any information on how to do this. So, I've got a service that defines
this.totalCount = 0;
In my controller, my get request retrieves some emails and then executes a function called addMessage for each message it retrieves. The addMessage function is in my service.
The function in my service looks like this:
this.addMessage = function (messageObj) {
this.messagesList.push(messageObj);
}
Basically, I am trying to increment this.totalCount each time this function is executed so that it will update and then can be displayed in the view. I have it displaying in the view currently, however its number always remains 0.
I've tried the following:
1.
this.addMessage = function (messageObj) {
this.messagesList.push(messageObj);
this.totalCount++;
}
2.
var count = this.totalcount
this.addMessage = function (messageObj) {
this.messagesList.push(messageObj);
count++; //and then attempted to display this value in the view but with no luck
}
Any tips would be greatly appreciated.
try this:
var that = this;
this.addMessage = function (messageObj) {
that.messagesList.push(messageObj);
}
I assume that you're binding the var this way in your controller and your view
Service :
this.totalCount = 0;
this.totalCount++;
Controller :
$scope.totalCount = service.totalCount;
view :
{{totalCount}}
And if you're actually doing it like this, you should face this kind of trouble.
The main problem is that totalCount is a primitive var and doing this.totalCount++ will break the reference. If you want to keep some var you should bind it as a sub-object.
This way :
Service :
this.utils = {};
this.utils.totalCount = 0;
this.utils.totalCount++;
Controller :
//This is the most important part. You bind an object. Then even if you loose the totalCount reference, your object will keep its own reference.
$scope.myServiceUtils = service.utils;
View :
{{myServiceUtils.totalCount}}
Actually in service (it's a matter of taste) i prefer a lot to use the object syntax instead of this (as "this" can be confusing)
This way :
var service = {};
service.utils.totalCount = 0;
service.addItem = function(){
...
}
return service;
Hope that was your issue.
You pass argument to another function which has different scope than your service. It is trick with assigning current object to variable, which is visible from function.
var that = this;
this.addMessage = function (messageObj) {
that.messagesList.push(messageObj);
that.totalCount++;
}
Should work.
So you assign that variable with current object, which is visible in inner function scope.
In a function addMessage body, this refers to function scope which is new, and there is no compiler error, but messagesList is a null object and totalCount is incremented, but after program leave function, it's not visible in service, because it is in a function scope which isn't assigned to any variable.
To update service variable as it changes in your controller, use $watch.
$scope.$watch(function() {
return messagesService.totalCount;
}, function(new,old){
$scope.totalmessagecount = messagesService.totalCount;
});
First parameter of $watch if function which return observed for change element. Another is standard function to perform operation after update.
var barcodeNum = ko.observable("");
VelocityMeetings.scan = function (params) {
var errorMessage = ko.observable("");
var viewModel = {
errorMessage: errorMessage,
scannumber: ko.observable(""),
errorVisible: ko.computed(function () {
return errorMessage().length != 0;
}),
scanBarcode: function () {
//Capture image with device and process into barcode
capturePhoto();
this.scannumber(barcodeNum());
//this.errorMessage(errMessage);
},
};
return viewModel;
};
I have the barcodeNum variable created outside of the view model, to try and pass data back into the scannumber variable. How do I access a variable defined inside of a view model?
The goal is to use the javascript Worker I have, to update the scannumber which will update my app accordingly, but I can't get it to function properly.
function receiveMessage(e) {
barcodeNum("Test function");
}
var DecodeWorker = new Worker("js/BarcodeScanner.js");
DecodeWorker.onmessage = receiveMessage;
The goal is something along the lines of this
VelocityMeetings.scan.viewModel.scannumber(barcodeNum());
but this isnt working properly
When you find yourself working with separate view models that have to communicate with each other, consider using knockout-postbox. You can make the communication one-way or two-way if you want. In your case, I think a one-way communication will be enough.
var barcodeNum = ko.observable('').publishOn('barcodeNum');
var viewModel = {
scannumber: ko.observable().subscribeTo('barcodeNum'),
// ...
};
I found the issue my self
scannumber: ko.observable(""),
scannumber can be defined as ko.computed with the return value being barcodeNum(), that will make any change made to barcodeNum also made to scannumber()
here is my computed
scannumber: ko.computed(function () { return barcodeNum(); },this),
I have been through this problem a lot of times before.. Then I decided to write an article on same...
You can refer to this article : http://www.wrapcode.com/knockoutjs/communication-between-multiple-view-models-in-knockoutjs-mvvm-the-right-approach/
I have explained how to deal with multiple view models and separate instances of multiple view models in this article..
Hope others will find it helpful :-)
Trying to learn Backbone and hitting a stumbling block when trying to fetch data, I fetch the data fine from with my view SearchBarView but once the data has been fetched I don't know how I can get this data in my SearchResultsView in order to template out each result?
Sorry if this sounds a little vague, struggling to get my head around this at the moment so could do with the guidance!
SearchBarView
performSearch: function(searchTerm) {
// So trim any whitespace to make sure the word being used in the search is totally correct
var search = $.trim(searchTerm);
// Quick check if the search is empty then do nothing
if(search.length <= 0) {
return false;
}
// Make the fetch using our search term
dataStore.videos.getVideos(searchTerm);
},
Goes off to VideoSearchCollection
getVideos: function(searchTerm) {
console.log('Videos:getVideos', searchTerm);
// Update the search term property which will then be updated when the url method is run
// Note make sure any url changes are made BEFORE calling fetch
this.searchTerm = searchTerm;
this.fetch();
},
SearchResultsView
initialize: function() {
// listens to a change in the collection by the sync event and calls the render method
this.listenTo(this.collection, 'sync', this.render);
console.log('This collection should look like this: ', this.collection);
},
render: function() {
var self = this,
gridFragment = this.createItems();
this.$el.html(gridFragment);
return this;
},
createItems: function() {
var self = this,
gridFragment = document.createDocumentFragment();
this.collection.each(function (video) {
var searchResultView = new SearchResultView({
'model': video
});
gridFragment.appendChild(searchResultView.el);
}, this);
return gridFragment;
}
Now I'm not sure how I can get this data within SearchResultView, I think I need to trigger an event from somewhere and listen for the event in the initialize function but I'm not sure where I make this trigger or if the trigger is made automatically.
Solution 1
If dataStore is a global variable then
SearchBarView
dataStore - appears like a global variable
videos - a collection attached to global variable
then in
SearchResultsView
this.listenTo(dataStore.videos, 'sync', this.render);
Solution 2
If dataStore is not a global variable
getVideos: function(searchTerm) {
console.log('Videos:getVideos', searchTerm);
// Update the search term property which will then be updated when the url method is run
// Note make sure any url changes are made BEFORE calling fetch
this.searchTerm = searchTerm;
var coll=this; //this should refer to the collection itself
this.fetch().done(function(){
var searchResultView = new SearchResultsView({collection:coll});
searchResultView.render();
});
},
It is not 100% clear how you are initializing your SearchResultView.
But, in order to have reference to the collection, can't you simply pass in the reference to the constructor of the view. Something like this:
// In your SearchbarView
var myCollection = new Backbone.Collection(); // and you are populating the collection somewhere somehow
var searchResultView = new SearchResultView(myCollection) // you just pass this collection as argument.
myCollection.bind("change", function(){
searchResultView.parentCollection = myCollection;
}
And inside your searchResultView you just refer this collection by parentCollection for instance.
If you make it more explicit as in how these 2 views are connected or related, I may be able to help you more. But, with given info, this seems like the easiest way.
I am having trouble getting data binding to work with Knockout when using revealing module pattern.
my javascript is like this
var HMS = HMS || {};
$(function () {
HMS.PatientModel = function () {
this.Patient_Name = ko.observable();
this.Patient_Address = ko.observable();
};
HMS.PatientViewModel = function () {
var patient = ko.observable(),
loadPatient = function () {
patient = new HMS.PatientModel();
patient.Patient_Name("Premkumar");
};
return {
patient: patient,
loadPatient: loadPatient
};
} ();
HMS.PatientViewModel.loadPatient();
ko.applyBindings(HMS.PatientViewModel);
});
I am unable to get the data binding to work with patient name properly. The HTML div tag has data-bind="text:patient.Patient_Name".
Please refer to the code in jsFiddle http://jsfiddle.net/stprem/pp9ym/1/. I would appreciate if you could tell me what I am doing wrong in data binding.
In your loadPatient function you are replacing the patient variable with a new object, but your module already returned a reference to the original observable. So, updating it in this way will not update what the object returned.
Here is an option: http://jsfiddle.net/rniemeyer/pp9ym/6/
Basically, you keep patient as an observable and then update it in your loadPatient function. In your view, using the with binding can help you protect against your object being null, in case you want to load it after you call ko.applyBindings.