I get undefined whenever I get the value of a property of an object.
function run(id){
var report = services.getReportInfo(id);
var childReport = {
id: newGuid(),
parentId: report.id, // i get undefined
reportPath: report.path // i get undefined
};
...
}
services.js
angular.module('project.services').factory('services', function(){
var reports = [
{
....
},
{
....
}
];
function getReportInfo(id){
var report = reports.filter(function(element){
return element.id === id;
});
};
return{
getReportInfo: getReportInfo
};
}
Whenever I put breakpoint on my var report = services.getReportInfo(id) it could contains the correct values for each property of the my report object. However, when I get the report.id or report.path, I get undefined value.
--Edited--
Oh, I know now where I got wrong.
The getReportInfo function returns an array and I'm accessing the properties without telling from what index should it get the values for the said properties.
function run(id){
var report = services.getReportInfo(id);
var childReport = {
id: newGuid(),
parentId: report[0].id,
reportPath: report[0].path
};
...
}
I placed static index 0, since I know that the array will always have a length of 1.
You are not returning anything from the .factory method and the getReportInfo is also not returning anything. For what you are trying to do, try to use .service method:
angular.module('project.services').service('services', function(){
var reports = [
{
....
},
{
....
}
];
this.getReportInfo = function (id){
var report = reports.filter(function(element){
return element.id === id;
});
return report;
}
}
Here is a good explanation on how to use .factory and .service:
Confused about Service vs Factory
Two immediate issues with the code I can see:
1) Your factory function needs to return a value or constructor function. Right now your code is not initializing the factory to any value.
2) Your getReportInfo function also doesn't return a value, yet you are assigning the function result to a variable.
Read more here: http://docs.angularjs.org/guide/dev_guide.services.creating_services
Related
What am I doing wrong, and how can one pass variables to a different function within the same wrapping variable/function.
Example:
function customFunctionWrap(){
this.myVar1 = 0;
this.getCurrentPosition = function(){
if (navigation.geolocation) {
navigator.geolocation.getCurrentPosition(function(position){});
}
},
this.doSomething = function(){ // Works
//Do something, return
this.callWithParams(); //Works
},
//If I remove passing in 'value1',calling it elsewhere works
this.doSomethingWithParams = function(value1){
//Use value1
//Return
},
this.callWithParams = function(){
var value1 = 'xyz'; //Is a variable that changes based on some DOM element values and is a dynamic DOM element
this.doSomethingWithParams(value1); //THROWS TYPEDEF ERROR: this.doSomethingWithParams is not a function
this.getCurrentPosition();
}
};
var local = new customFunctionWrap();
local.doSomething(); //WORKS
I know there is another way to do it and then directly use customFunctionWrap.callWithParams(), but am trying to understand why the former approach is erroring out.
var customFunctionWrap = {
myVar1 : 0,
callWithParams : function(){
}
}
What JS sees:
var customFunctionWrap = (some function)()
returned function is fired, because the last (), so it has to yield/return something, otherwise, like in your code it is "returning" undefined.
So your given code does not work.
The very first fix is to delete last 2 characters from
var customFunctionWrap = (some function)()
to make it return constructor.
This might be a stupid problem, but I have an object in which I wanted to store references of other functions/variables and later use them.
For example,
var obj = {
keyA: {
ref: window.objects.someAAA
},
keyB: {
ref: window.objects.someBBB
}
}
Here, when I set this object, window.objects is empty, so accessing those keys (someAAA and someBBB) will give undefined.
I know I was dumb when I first thought of assigning them like this and expecting their actual values after they're loaded, to be available via obj.keyA and obj.keyB. But obviously, they still contain undefined.
But is there a way to do that! I know if I set string instead of reference, I can eval, but any better solution?
Think this should work
var obj = {
keyA: {
ref: function() { return window.objects.someAAA; }
},
keyB: {
ref: function() { return window.objects.someBBB; }
}
}
You can then access via
obj.keyA.ref()
Test
Add the code above then do
window['objects'] = {};
window['objects']['someAAA'] = 'Hallo';
obj.keyA.ref() // will Output 'Hallo'
Try using Getters for such case:
var obj = {
get keyA(){
return (window['objects'])? window.objects.someAAA : null
},
get keyB() {
return (window['objects'])? window.objects.someBBB : null
}
}
// as now window.objects doesn't exists
console.log(obj.keyA); // outputs "null"
window.objects = {'someAAA': "aaa-value", 'someBBB': "bbb-value"};
console.log(obj.keyA, obj.keyB); // outputs "aaa-value" "bbb-value"
I am using a complex object graph serialized to JSON with MVC4/jQuery/Sammy/Rivets for SPA functionality.
I have a object graph that looks a bit like this when serialized to JSON (obviously mocked-up):
model =
{
Name: "Me",
Age: 22,
Hobbies:
[
{ Name: "Biking", IsActive: true },
{ Name: "Programming", IsActive: true }
]
}
Everything works quite well until I need Unobtrusive validation, since my Hobbies are in a SlickGrid and I am managing all the data myself. To handle this I am returning my ModelState with my JSON next to my model.
return JSON(new { model = model, modelState = this.ModelState });
From there I intend to iterate through the modelState and assign errors to the right place with some custom function, but there is one problem.
ModelState looks like this:
"Name",
"Age",
"Hobbies[0].Name",
"Hobbies[0].IsActive",
"Hobbies[1].Name",
"Hobbies[1].IsActive"
I need to separate the [0]'s into an object and [1]'s into their own objects so I can smoothly get the values. This gets confusing for me when I begin to account for a third level of complex object array.
Solution:
var ModelStateConverter = function ($, module) {
module = module || {};
// Convert The ModelState form style object to a standard JS object structure.
module.toObject = function (modelState) {
var ModelState = {};
$.each(modelState, function (key, value) {
AssignValuesToObjectStore(key, ModelState, value);
});
return ModelState;
}
// item is the full identifier ex. "Hobbies[0].Name"
// store is the object we are going to throw arrays, objects, and values into.
// value is the error message we want to get in the right place.
// index is an internal processing parameter for arrays only, setting it's value has no effect.
function AssignValuesToObjectStore(item, store, value, index) {
var periodMatch = item.match(/[\.]/);
if (periodMatch === null) {
if (Array.isArray(store)) {
if (store[index] === undefined) {
store[index] = {};
}
store[index][item] = value;
}
else {
store[item] = value;
}
}
else {
// This wasn't a simple property or end of chain.
var currentProperty = item.slice(0, periodMatch.index); // Get our property name up to the first period.
var container = {}; // We assume we are dealing with an object unless proven to be an array.
var arrayIndex; // This is irrelevant unless we have an array.
if (currentProperty.slice(-1, currentProperty.length) === "]") {
// We are dealing with an array! Hoo Ray?!
arrayIndex = parseInt(currentProperty.slice(currentProperty.indexOf("[") + 1, currentProperty.indexOf("]")));
currentProperty = currentProperty.slice(0, currentProperty.indexOf("[")); // remove the indexer ex. [0] so we are left with the real name
container = []; // We know we need an array instead;
}
if (store[currentProperty] === undefined) {
store[currentProperty] = container; // If this property isn't already created, then do so now.
}
//Recurseive nature here.
AssignValuesToObjectStore(item.slice(periodMatch.index + 1, item.length), store[currentProperty], value, arrayIndex);
}
}
return module;
}($, ModelStateConverter);
You can call this from:
ModelStateConverter.toObject(data.modelState);
Where data.modelState is assumed to be the ModelState from the server.
You could try a library like JSON.NET, or the class JavaScriptSerializer, to serialize the ModelState.
I am stuck with the following situation. I have a select statement which uses a function in the current scope me. How do I go about putting me into the select function?
var me = this;
var results = Enumerable
.from(jsonData)
.select('x,i=>{abbr:me.transform(x), name:x}')
.toArray(); //me.transform(x) will hit error
'me' is an instance of a dynamically generated object, and me.transform(x) uses other dependencies in 'me' to work as well. That means I cannot make 'me.transform()' global function.
EDIT
var me = this;
var results = Enumerable
.from(jsonData)
.select(function(x,i){
return {abbr:me.transform(x), name:x};
}).toArray();
Actually, this modification will work, however, I would like to find out the how to make the shortcut syntax work.
What you could do is project your objects to a composite object containing both the item in the collection and the object you want to introduce into the query.
You can use this Capture function to capture the variables:
function Capture(bindings, name) {
var benumerable = Enumerable.From(bindings),
itemname = name || 'Item';
return function (e) {
return e.Select(function (item) {
return benumerable.Concat(Enumerable.Return({ Key: itemname, Value: item }))
.ToObject("$.Key", "$.Value");
});
};
}
Use it in a Let binding.
var query = Enumerable.From(data)
.Let(Capture({ Me: me }))
.Select("{ abbr: $.Me.transform($.Item), name: $.Item }")
.ToArray();
My bad. Is this what you mean?
var me = this;
var results = Enumerable
.from(jsonData)
.select('x,i=>{abbr:' + me.transform(x) + ', name:x}')
.toArray(); //me.transform(x) will hit error
I have this code:
collection = (function() {
function collection(removeLinkTitle){
this.removeLinkTitle = removeLinkTitle || 'delete';
}
collection.prototype = {
removeLinkTitle: this.removeLinkTitle,
init:function(){
...some code...
this.deleteCollectionForm();
},
deleteCollectionForm:function(){
var removeFormA = $(''+this.removeLinkTitle+'');
linkLi.append( removeFormA );
removeFormA.on('click', function(e) {
e.preventDefault();
linkLi.remove();
var index = collectionHolder.data( 'index' );
collectionHolder.data( 'index', index - 1 );
});
}
};
return collection;
})();
The thing is that the var removeForm returns its value only the frst time it loads, the following times it returns undefined.
I don't want to pass the variable as an argument so, is it there any other way to do this?
Thanks !!
i think this is not really the problem, the one thing that is undefined is the, removeLinkTitle, try this:
return new collection;
so you hit your constructor, or set some other value with:
return new collection("delete item");