How to assign a back end data value to a string variable in AngularJS? - factory

I was trying to define one sort of global variable which value will be reflecting in 2/3 different templates (directives). For that I used angular factory as follows:
app.factory('MyService', function ($http) {
return {
firstNumber: function (){
//return selectedNumber = "200";
var selectedNumber = "";
var selectedNumber = $http.get("/count.do").success(function (data) {
console.log('First Number: ', data[0].count)
});
return selectedNumber;
}
};
});
As you can see 'selectedNumber' is that common variable. Problem is when I am hard coding the value as "200" and from controller calling as follows:
//Init Number
$scope.selectedNumber= MyService.firstNumber();
This whole process is working fine. But as soon as I am trying to get the value from back end (which you can see above) getting {} object.
I did some research on this and understanding that my concept on Angular object and String manipulation is not clear...can anyone please help me to understand the mistake I am doing and to resolve this situation.

Well, i got my expected outcome by using 'callback' service as follows:
In my factory i just called the '$http.get':
app.factory('MyService', function ($http) {
return {
firstNumber: function (){
$http.get("/count.do").success(callback);
}
};
});
And then from controller i received the data and assigned as follows:
//Init Number
MyService.firstNumber(function(data) {
$scope.selectedNumber = data[0].count;
});
I don't know whether it is a good solution or what, will really appreciate for any comment on this solution plz.
Thanks

Related

parse.com destroyAll not working

In the code following this description, I am trying to find and remove all these bad ListConfig objects that didn't have a group object set. It is correctly finding them, however it does not remove them. Is there something I am missing in the following code?
var Groups = [];
function queryForGroups(callback) {
var Group = Parse.Object.extend("Group");
var query = new Parse.Query(Group);
query.limit(1000);
query.find().then(function(result) {
Groups = result;
callback();
});
};
function removeConfigs(){
var Config = Parse.Object.extend("ListConfig");
var query = new Parse.Query(Config);
query.limit(10000);
query.notContainedIn("group", Groups);
query.find().then(function(configs){
return Parse.Object.destroyAll(configs, {useMasterKey:true});
});
}
function removeBadConfigs() {
queryForGroups(function() {
removeConfigs();
});
};
removeBadConfigs();
The code could be a little cleaner with respect to mixing promises, callbacks and an unnecessary global. Beyond that, it looks like it should work as long as your data model supports it. Specifically, your ListConfig object must have a "group" property, and it must have a Parse.Object value set for that property. The most common error I've seen is something like this:
var myGroup = // a parse object of type Group
myListConfig.set("group", myGroup.id); // WRONG
myListConfig.set("group", myGroup); // RIGHT
Assuming you've got that right, then it's mysterious why you're not seeing some deletes, but here's the code cleaned up with promises...
function queryForGroups() {
let query = new Parse.Query("Group")
query.limit(1000);
return query.find();
};
function removeConfigsWithGroups(groups){
let query = new Parse.Query("Config");
query.notContainedIn("group", groups);
return query.find().then(function(configs){
return Parse.Object.destroyAll(configs, {useMasterKey:true});
});
}
function removeBadConfigs() {
return queryForGroups(function(groups) {
return removeConfigsWithGroups(groups);
});
};
removeBadConfigs();
I figured it out. I removed "useMasterKey: true" because 1) it isn't needed for objects not with elevated privileges and 2) I was not running it in Cloud Code.

Angular Meteor objects not acting as expected

I am working with Angular Meteor and am having an issue with my objects/arrays. I have this code:
angular.module("learn").controller("CurriculumDetailController", ['$scope', '$stateParams', '$meteor',
function($scope, $stateParams, $meteor){
$scope.curriculum = $meteor.object(CurriculumList, $stateParams.curriculumId);
$scope.resources = _.map($scope.curriculum.resources, function(obj) {
return ResourceList.findOne({_id:obj._id})
});
console.log($scope.resources)
}]);
I am attempting to iterate over 'resources', which is a nested array in the curriculum object, look up each value in the 'ResourceList' collection, and return the new array in the scope.
Problem is, sometimes it works, sometimes it doesnt. When I load up the page and access it through a UI-router link. I get the array as expected. But if the page is refreshed, $scope.resources is an empty array.
My thought is there is something going on with asynchronous calls but have not been able for find a solution. I still have the autopublish package installed. Any help would be appreciated.
What you're going to do is return a cursor containing all the information you want, then you can work with $meteor.object on the client side if you like. Normally, publishComposite would look something like this: (I don't know what your curriculum.resources looks like)
Use this method if the curriculum.resources has only ONE id:
// this takes the place of the publish method
Meteor.publishComposite('curriculum', function(id) {
return {
find: function() {
// Here you are getting the CurriculumList based on the id, or whatever you want
return CurriculumList.find({_id: id});
},
children: [
{
find: function(curr) {
// (curr) will be each of the CurriculumList's found from the parent query
// Normally you would do something like this:
return ResourceList.find(_id: curr.resources[0]._id);
}
}
]
}
})
This method if you have multiple resources:
However, since it looks like your curriculum is going to have a resources list with one or many objects with id's then we need to build the query before returning anything. Try something like:
// well use a function so we can send in an _id
Meteor.publishComposite('curriculum', function(id){
// we'll build our query before returning it.
var query = {
find: function() {
return CurriculumList.find({_id: id});
}
};
// now we'll fetch the curriculum so we can access the resources list
var curr = CurriculumList.find({_id: id}).fetch();
// this will pluck the ids from the resources and place them into an array
var rList = _.pluck(curr.resources, '_id');
// here we'll iterate over the resource ids and place a "find" object into the query.children array.
query.children = [];
_.each(rList, function(id) {
var childObj = {
find: function() {
return ResourceList.find({_id: id});
}
};
query.children.push(childObj)
})
return query;
});
So what should happen here (I didn't test) is with one publish function you will be getting the Curriculum you want, plus all of it's resourceslist children.
Now you will have access to these on the client side.
$scope.curriculum = $meteor.object(CurriculumList, $stateParams.curriculumId);
// collection if more than one, object if only one.
$scope.resources = $meteor.collection(ResoursesList, false);
This was thrown together somewhat quickly so I apologize if it doesn't work straight off, any trouble I'll help you fix.

using a function defined in a kendo model later in that model

OK, I'm obviously not understanding how functions are used in javascript. Given the below code snippet, mozilla firefox is telling me that calcUpper is not defined. Basically I want to define a function and use that function later on in the view on different fields. I tried moving the function definition outside of the kendo model, but with no better results. Can someone show me how I can achieve this?
var viewModel = kendo.observable({
calcUpper: function (fieldName) {
var value = this.get(fieldName);
if (value == "")
return "";
else
return parseInt(value) - 1;
},
jobNum: '',
SRCPerif: '',
SRCOnTargetUpper: calcUpper('SRCPerif'),
SRCOnTargetLower: '',
SRCConcernUpper: calcUpper('SRCOnTargetLower'),
//...other fields...
});

Knockout validation issues

I have the following issues with my knockout model validations and not sure how to resolve them. Following is my model first of all, with the validation rules:
var Data = function (data) {
this.Val = data;
}
function ViewModel(item) {
var parse = JSON.parse(item.d);
var self = this;
this.Name = ko.observable(parse.Name);
this.UserType = ko.observable(parse.UserType);
this.ID = ko.observable(parse.ID).extend({ required: { params: true, message: "ID is required" }, decimal: { params: 2, message: "Should be decimal"} });
this.Username = ko.observable(parsed.Username).extend({ required: {
onlyIf: function () {
return self.UserType() > 1;
}
}
});
this.WeeklyData = ko.observableArray([]);
var records = $.map(parse.WeeklyData, function (data) { return new Data(data) });
this.WeeklyData(records);
this.WeeklyData2 = ko.observableArray([]);
var records = $.map(parse.WeeklyData2, function (data) { return new Data(data) });
this.WeeklyData2(records);
}
ko.extenders.numeric = function (target, precision) {
var result = ko.dependentObservable({
read: function () {
return target().toFixed(precision);
},
write: target
});
result.raw = target;
return result;
};
Here are my problems:
1) with the ID() observable, I want to restrict it to two decimal points, so I've created the validation extender 'numeric' but it's not working. Is there anything wrong with how I'm using it and how to correct it?
2) Also, if I want to restrict an observable to whole numbers, how can I do that?
3) when I define a rule with a condition, (i.e. Username()), how do I define a custom message for that? I was able to do it for default rules, but with the conditional rules, it's not working
4) I have two observable arrays WeeklyData1 and WeeklyData2 both of which contains Data() objects. I want to have separate min/max rules for these two, for example, min/max - 1,7 for WeeklyData1 and min/max - 1,150 for WeeklyData2. How can I get it done?
4) Right now my error messages appear right next to the data field, but I want all those to appear in a single validation summary, while displaying '*' against the field. I've been told to use Validation-bindings, but I'm not sure how to use it, can someone please give an example?
It's a lot of questions, I know, but I appreciate if someone could help.
Thanks in advance
Instead of diving in your code i have created a small-small demonstrations for your questions. Ok so here we go,
1) with the ID() observable, I want to restrict it to two decimal points.... and 2) Also, if I want to restrict an observable to whole numbers....
Your 1 and 2 question are pretty similar so i covered both of this in a single fiddle. Check this fiddle.
3) when I define a rule with a condition, (i.e. Username()), how do I define a custom message ....
You can use message property to set custom messages, Check this fiddle.
4) I have two observable arrays WeeklyData1 and WeeklyData2 both of which contains Data() objects
I am not clear which this question, what type of data both of these array contains and for what you want to set min/max rule ( array length or other ). So please clear this, than i will try to help on this.
5) Right now my error messages appear right next to the data field.....
This questions answer i already given in your how to? with knockout js validations question (Check update).
Let me know if it helps!

Backbone.js: How to call methods on the collection within an object literal

I have the following backbone.js code. I'm using an object literal for organizing my code, which has left me with a question regarding the best way to proceed. The application (in its simplified form below) has a control panel (which can be shown or hidden) which is used to add new categories to a collection. (Question follows)
(function($){
// ============================= NAMESPACE ========================================
var categoryManager = categoryManager || {};
// ============================= APPLICATION =================================================
categoryManager.app = categoryManager.app || {
/* Used to Initialise application*/
init: function(){
//this.addView = new this.addCategoryView({el: $("#add-new-category")})
//this.collection = new this.categoryCollection();
new this.addCategoryView({el: $("#add-new-category")})
new this.categoryCollection();
},
categoryModel: Backbone.Model.extend({
name: null
}),
addCategoryView: Backbone.View.extend({
events: {
"click #add-new-category-button.add" : "showPanel",
"click #add-new-category-button.cancel" : "hidePanel",
"click #new-category-save-category" : "addCategory"
},
showPanel: function() {
$('#add-new-category-button').toggleClass('add').toggleClass('cancel');
$('#add-new-category-panel').slideDown('fast');
},
hidePanel: function() {
$('#add-new-category-button').toggleClass('add').toggleClass('cancel');
$('#add-new-category-panel').stop().slideUp('fast');
},
addCategory: function() {
//categoryManager.app.collection.create({
categoryManager.app.categoryCollection.create({ // My Problem is with this line
name: $('#name').val()
});
}
}),
categoryCollection: Backbone.Collection.extend({
model: this.categoryModel,
initialize: function () {
}
})
}
// ============================= END APPLICATION =============================================
/* init Backbone */
categoryManager.app.init();
})(jQuery);
Now obviously the problem with the above, is that calling the addCategory function tries to call a function on an object which is uninitialized. I've worked round the problem (see commented out code) by calling the function instead on a object which is instantiated within the init function. My question is - is this the right thing to do? I detect a code smell. I feel that the contents of the object literal shouldn't rely on the object being created in order to be valid. the function addCategory in this instance wouldn't work unless the init function had been called on the parent first. Is there another pattern here that I should be using?
How else would I pass the contents of the 'create new category form' to the collection in order to be added (I'm using create because I want to automatically validate/create/persist the model and It seems like the easiest thing to do). I'm a rock bottom novice with backbone (this is my 'hello world')
Thanks
I think the main issue is you are treating categoryCollection as if it's an object. It's not really an object, but a constructor function. So first you need to create an instance, as you have discovered.
Then the addCategoryView needs some way of referencing the instance. It looks like you don't have a model associated with the view. I would suggest creating a model and storing the categoryCollection instance as a property of the model. Something like this (warning, untested code):
var model = new BackBone.Model({
categories: new categoryManager.app.CategoryCollection()
});
var view = new categoryManager.app.AddCategoryView({
el: $("#add-new-category"),
model: model
});
Then you can just use this.model.categories from inside addCategoryView.
As an aside, a common Javascript convention is to capitalize the names of constructors. Calling the constructor CategoryCollection might make the code a little bit clearer.
You need to initialize collection before create a new instance of a model
addCategory: function() {
var collection = categoryManager.app.categoryCollection;
!collection.create && (collection = new collection);
collection.create({
name: $('#name').val()
});
}

Resources