I am trying to set a variable that will depend on two others, but I don't want that computed
variable reacts on the initializing of one of these vars.
var viewModel = function() {
var self = this;
self.first = ko.observable("");
self.second = ko.observable();
self.doSmth = function() {
self.second(self.second() + 1);
};
self.init = function(o){
self.second(o);
};
self.comp = ko.computed(function(){
self.first();
self.second();
alert(self.second());
});
};
var vm = new viewModel();
ko.applyBindings(vm);
vm.init(111);
http://jsfiddle.net/TCAHS/1/
Alert message should appear only when I click on the button and dependent variable value was changed. And no messages with 'undefined' and init value '111'. Is there any built-in solution? Thanks.
I'll go with the easy solution... what about setting a flag to check whether the observable has been initialized, something like:
var viewModel = function() {
var self = this;
self.first = ko.observable("");
self.second = ko.observable();
self.doSmth = function() {
self.second(self.second() + 1);
};
self.init = function(o){
self.second(o);
};
var initialized = false;
self.comp = ko.computed(function(){
self.first();
self.second();
if (initialized) {
alert(self.second());
}
initialized = true;
});
};
var vm = new viewModel();
ko.applyBindings(vm);
vm.init(111);
And here's the fiddle.
Related
This is a model and I am trying to access its values. But value is in Symbol(_latestValue) and I am not sure how I can access that value.
define(['services/SessionService'],
function(SessionService) {
var uiModel = function(index, data) {
this.origData = data;
this.sessionID = data.sessionID;
this.rowNumber = index + 1;
this.FullName = ko.observable('');
this.accountId = ko.observable('');
this.organizationId = ko.observable('');
this.userId = ko.observable('');
this.BuyerEmail = ko.observable('');
this.Address = ko.observable('');
this.loadSessionInfo();
};
uiModel.prototype.loadSessionInfo = function() {
var self = this;
var service = new SessionService();
service.getSessionInfo(this.sessionID).then(function(result) {
self.FullName(result.Buyer1Name);
self.BuyerEmail(result.BuyerEmail);
self.Address(result.Address);
self.accountId(result.AccountID);
self.organizationId(result.OrganizationID);
self.userId(result.UserID);
});
};
return uiModel;
});
Attached is the image that shows values that I am receiving are in Symbol(_latestValue).
Hi folks trying to get a simple setintervel working to automatically refresh my data every minute. The line im having issues with is this:
setInterval(incidentViewModel.fetchdata,60000);
I had also tried this:
window.setInterval(incidentViewModel.fetchdata,60000);
Both of these give me the same error:
Uncaught TypeError: self.incidents is not a function
Im not seeing anything obvious that's causing the problem, would anyone have any idea?
Here is my full code:
function IncidentViewModel() {
var self = this;
self.incidents = ko.observableArray();
self.currentIncident = ko.observable();
self.showModal = ko.observable(false);
self.fetchdata = function() {
Incident.BASE_URL = '../../../../_vti_bin/listData.svc/GDI_PROD_Incidents';
Incident.CREATE_HEADERS = {"accept": "application/json;odata=verbose"};
Incident.UPDATE_HEADERS = {"accept": "application/json;odata=verbose","If-Match": "*"};
var self = this;
$.getJSON(Incident.BASE_URL+filterlist+orderlist,
function(data) {
if (data.d.results) {
self.incidents(data.d.results.map(function(item) {
return new Incident(item);
}));
$('#loading').hide("slow");
$('#IncidentTable').show("slow");
} else {
console.log("no results received from server");
}
}).fail(function() {
console.log("error", params, arguments);
});
console.log("Im done fetching data, pheww!");
}
}
function DataItem(data) {
//console.log(data);
this.Name = ko.observable(data.Name);
this.Price = ko.observable(data.Price);
}
function Incident(data) {
var self = this;
self.ID = data.ID;
self.Description = ko.observable(data.Description);
self.Composante = ko.observable(data.Composante);
self.Incident = ko.observable(data.Incident);
self.ÉtatValue = ko.observable(data.ÉtatValue);
self.PrioritéValue = ko.observable(data.PrioritéValue);
self.Duré = ko.observable(data.Duré);
self.Date_de_début = ko.observable(data.Date_de_début);
self.Date_de_fin = ko.observable(data.Date_de_fin);
self.Groupe_Support_Prime = ko.observable(data.Groupe_Support_Prime);
self.Autres_Groupe_Support_Prime = ko.observable(data.Autres_Groupe_Support_Prime);
self.ResponsableValue = ko.observable(data.ResponsableValue);
self.Impact = ko.observable(data.Impact);
self.Temps_Consacré = ko.observable(data.Temps_Consacré);
self.Type_de_tempsValue = ko.observable(data.Type_de_tempsValue);
self.Journal_des_actions = ko.observable(data.Journal_des_actions);
self.Dépanage = ko.observable(data.Dépanage);
self.Journal_des_actions = ko.observable(data.Journal_des_actions);
self.Suivi = ko.observable(data.Suivi);
self.Ressources = ko.observable(data.Ressources);
}
var incidentViewModel = new IncidentViewModel();
ko.applyBindings(incidentViewModel);
setInterval(incidentViewModel.fetchdata,60000);
Remove var self = this; inside the self.fetchdata function because you should be referring to the self inside the IncidentViewModel function when referring to self.incidents().
I've started using Knockout JS and I applied a textarea counter to my viewmodel. But for some reason I get the error message:
TypeError: self.description(...) is undefined
var counter = self.description().length;
Even my teset fiddle doesn't work.
My code is this:
//HTML
<textarea data-bind="value: description, valueUpdate: 'afterkeydown'"></textarea>
//JS
jQuery(document).ready(function($) {
ko.applyBindings(specialOfferPreviewModel());
});
function specialOfferPreviewModel() {
// -- This part works
var self = this;
self.promoTitle = ko.observable();
self.description = ko.observable();
self.fromDate = ko.observable();
self.toDate = ko.observable();
// To and from date
self.validPeriod = ko.computed(function() {
return self.fromDate + " - " + self.toDate;
}, self);
// -- And this part breaks it
self.count = ko.computed(function(){
var counter = self.description().length;
return counter;
});
}
What am I missing? Any help appreciated!
Update:
I'm not sure the difference of these two, but either works:
//1
function specialOfferPreviewModel(){}
ko.applyBindings(specialOfferPreviewModel());
//2
var specialOfferPreviewModel = function(){}
var vm = new specialOfferPreviewModel ();
ko.applyBindings(vm);
They both work
Because the observable contains undefined as it hasn't been set.
By writing that :
self.description = ko.observable();
The observable contains undefined and you can see it if you decompose the code as follow :
self.description = ko.observable();
var content = self.description();
content.length;
In the fiddle :
var counter = self.description().length;
Is evaluated before it has been bound to the field, that's why its inner value is undefined.
So you can either initialize the observable :
self.description = ko.observable('');
Or you can defer the evaluation of the computed :
self.count = ko.computed({
read: function () {
var counter = self.description().length;
return counter;
},
deferEvaluation: true
});
See doc
I have a question about the promise system in AngularJS and the creation of services. I have a service called Customer:
angular.module("app").factory("Customer", ["CustomerDBServices", "OfficesList", "$q",
function(CustomerDBServices, OfficesList, $q){
return function(customerID){
var self = this;
//attributes
this.name = null;
this.ID = null;
this.code = null;
this.isVisible = 1;
this.showOffices = true;
this.offices = new OfficesList();
//constructor
if(typeof customerID !== "undefined"){
var metacustomer = CustomerDBServices.find({ID:customerID}, function(){
self.name = metacustomer.results.customer_name;
self.ID = metacustomer.results.customer_ID;
self.code = metacustomer.results.customer_internal_code;
self.isVisible = metacustomer.results.customer_is_visible;
self.getOffices();
});
}
//add office to customer
this.addNewOffice = function(){
self.offices.addNewOffice();
};
//remove office from customer
this.removeOffice = function(officeIndex){
self.offices.removeOffice(officeIndex);
};
//show offices
this.toggleOfficeVisibility = function(officeIndex){
self.offices.toggleOfficeVisibility(officeIndex);
};
}]);
In the "constructor" part of this service there is an AJAX call to a service that loads the attributes of the customer from the database. This is an async task. How can I create a promise in this situation? I use the customer service like this:
var customer = new Customer(ID);
and I would like to do something like
var customer = new Customer(ID).then(
function(){...}, //success
function(){...} //error
);
To do this I need a promise. Do I have to program a method create() within the customer service?
angular.module("app").factory("Customer", ["CustomerDBServices", "OfficesList", "$q",
function(CustomerDBServices, OfficesList, $q){
return function(customerID){
var self = this;
//attributes
this.name = null;
this.ID = null;
this.code = null;
this.isVisible = 1;
this.showOffices = true;
this.offices = new OfficesList();
//costructor
this.create = function(){
if(typeof customerID !== "undefined"){
var rest = $q.defer();
var metacustomer = CustomerDBServices.find({ID:customerID}, function(){
self.name = metacustomer.results.customer_name;
self.ID = metacustomer.results.customer_ID;
self.code = metacustomer.results.customer_internal_code;
self.isVisible = metacustomer.results.customer_is_visible;
self.getOffices();
rest.resolve("ok!");
});
return rest.promise;
}
}
...
...
...
}]);
and then use that stuff like this?
var customer = new Customer();
customer.create(ID).then(
function(){...},
function(){...},
)
Isn't there a way to call the "new Customer" and receive a promise? Thank you in advance!
Like I said in my comment I recommend against this approach. Putting complex asynchronous logic in a constructor is usually confusing and does not make for a very good or clear API.
That said, You don't need a .create method.
The trick is: If a function called as a constructor returns an object in JavaScript - it is returned instead of the this value.
Sparing you the whole Angular around it:
function(CustomerDBServices, OfficesList, $q){
return function(customerID){
var p = $q.defer();
var that = p.promise; // our 'that' is now a promise
//attributes
that.name = null;
that.ID = null;
that.code = null;
that.isVisible = 1;
that.showOffices = true;
that.offices = new OfficesList();
// use `that` instead of this in additional code
if(typeof customerID !== "undefined"){
var metacustomer = CustomerDBServices.find({ID:customerID}, function(){
self.name = metacustomer.results.customer_name;
self.ID = metacustomer.results.customer_ID;
self.code = metacustomer.results.customer_internal_code;
self.isVisible = metacustomer.results.customer_is_visible;
self.getOffices();
that.resolve("ok!");
});
}
return that; // we return the promise here.
}
I am getting has no method error
here is the sample code
var snake = function(){
this.initialize = function(){
// initalize
};
this.start = function() {
this.initialize();
};
};
var s = new snake();
var startButton = document.getElementByID("start");
startButton.addEventListener('click',s.start,false);
So when I click start button I am getting
Uncaught TypeError: Object # has no method 'initialize'
how can i fix this
Try
startButtons.addEventListener('click', function() { s.start() }, false);
The this in the function is going to be the input unless you use bind
Because of this. Use a private variable(snk) to ensure you are accessing the snake:
var snake = function(){
var snk = this;
this.initialize = function(){
// initalize
};
this.start = function() {
snk.initialize();
};
};
var s = new snake();
var startButton = document.getElementByID("start");
startButton.addEventListener('click',s.start,false);