JavaScript error when creating custom object - javascript

I am finding that when I call record.create() then sometimes it succeeds, and at other times it throws an error saying that no such method exists, even though record object has its properties set appropriately.
Am I using create method incorrectly? May be I am missing something about JavaScript custom object syntax.
<script language="javascript" type="text/javascript">
var record = {
RecordID : null,
CustomerID : null,
CompanyID : null,
create : function() {
var obj = new Object();
obj.RecordID = "";
obj.CustomerID = "";
return obj;
}
};
function pageLoad(sender, eventArgs) {
{
//*******SUCCEEDS********
record = record.create()
}
function RadGrid1_RowSelected(sender, args) {
currentRowIndex = args.get_gridDataItem().get_element().rowIndex;
var dataItem = args.get_gridDataItem().get_dataItem();
recordId = dataItem["Record_ID"];
if (tableView.get_selectedItems().length == 1) {
record = record.create();
record.RecordID = dataItem["Record_ID"];
record.CustomerID = dataItem["Customer_ID"];
setValues();
}
else if (tableView.get_selectedItems().length > 1) {
record= record.create();//****FAILS ALWAYS even when record object has non-null properties*******
}
if ($.inArray(recordId, recordIds) == -1) {
recordIds.push(recordId);
}
}
</script>
UPDATE : This is what worked for me.
Instead of using the create method on 'record' global object, I ended up using a simple approach. Just call a custom method 'resetRecord' everytime I wanted to call the create( ) method on record object. That way I have no errors and my logic works perfectly.
function resetRecord() {
record.RecordID = "";
record.CustomerID = "";
record.CompanyID = "";
}

It won't work after the first call because you are overwriting the record object. This will destroy any create() method as the object returned does not have this method/property.
For you update, variables have function level scope. You are using the global record inside of RadGrid1_RowSelected.
I'm not entirely sure what you are doing but this will get you past your first problem.
function RadGrid1_RowSelected(sender, args) {
var newRecord;
currentRowIndex = args.get_gridDataItem().get_element().rowIndex;
var dataItem = args.get_gridDataItem().get_dataItem();
recordId = dataItem["Record_ID"];
if (tableView.get_selectedItems().length == 1) {
record = record.create();
record.RecordID = dataItem["Record_ID"];
record.CustomerID = dataItem["Customer_ID"];
setValues();
}
else if (tableView.get_selectedItems().length > 1) {
newRecord= record.create();//****FAILS ALWAYS even when record object has non-null properties*******
}
if ($.inArray(recordId, recordIds) == -1) {
recordIds.push(recordId);
}
}

Related

Cannot read property 'push' of undefined

I am trying to push data attribute value into array parameter but it throws the above error on the line parameter[parent].push(parent);
var parameter = {};
var currentTabSelected = "";
var parent = "";
$("#categories").on("click", ":checkbox", function () {
if($(this).is(":checked")) {
parent = $(this).data("parent");
console.log(parent)
if (!(currentTabSelected in parameter)) {
parameter[currentTabSelected] = []
}
var found = $.inArray($(this).val(), parameter[currentTabSelected]) > -1;
if (!found) {
parameter[currentTabSelected].push($(this).val());
parameter[parent].push(parent);
console.log(parameter)
}
} else {
var index = parameter[currentTabSelected].indexOf($(this).val());
var parent_index = parameter[parent].indexOf(parent)
if (index > -1) {
parameter[currentTabSelected].splice(index, 1);
parameter[parent].splice(parent_index , 1);
}
}
})
what can i do to overcome the above problem?
If parameter is an object you should create keys before using them.
You are trying to access the key which is not present in the parameter.
For example , make sure your object contains currentTabSelected and parent:
parameter[currentTabSelected] = []
parameter[parent] = []
After initializing currentTabSelected and parent you can perform operation on parameter[currentTabSelected], parameter[parent].
I suffered from the same issue few days ago, the solution is directly related with the 'this' keyword. Your 'this' is referring to another scope that your variable is not a part of. You might want to do a
var that=this;
Or if you're comfortable with ES6, you can use the arrow function syntax.

Validate breeze complex-type without validate the entire entity

When you want to validate breeze-entity you write:
this.entityAspect.validateEntity()
But what about if I want to fire validations only for complex-type, without fire the entire-entity validations?
complexType.complexAspect not have method validateEntity.
So, what should I do?
Edit after I saw Jay answer:
I tried to use method validateProperty.
But the result was that it always returns true, becouse it not check each one of the properties.
So, I tried to call method validateProperty several-times, each time for other field of the complexType. It give me boolian-result of valid/not valid, but not update the validation-errors.
Here is the code that I tried after I saw Jay answer, but it is not help:
validateSingleField(myComplexProertyName);
first version of validateSingleField function: (the result was that it always returns true, becouse it not check each one of the properties)
function validateSingleField(object, fieldName) {
var entityAspect = object.entityAspect;
var objectType = object.entityType;
var prop = objectType.getProperty(fieldName);
var value = object.getProperty(fieldName);
if (prop.validators.length > 0) {
var context = { entity: entityAspect.entity, property: prop, propertyName: fieldName };
if (entityAspect._validateProperty(value, context)) {
return true;
}
return false;
}
}
second version:(It give me boolian-result of valid/not valid, but not update the validation-errors.)
function validateSingleField(object, fieldName) {
var aspect = object.entityAspect || object.complexAspect;
var entityAspect = object.entityAspect || object.complexAspect.getEntityAspect();
var objectType = object.entityType || object.complexType;
var prop = objectType.getProperty(fieldName);
if (prop.isComplexProperty) {
var isOk;
objectType.getProperties().forEach(function (p) {
isOk = isOk && validateSingleField(object[fieldName](), p.name)//writing 'object[fieldName]()' - is for send the entire complexType of the entity
});
return isOk;
}
else {
{
var value = object.getProperty(fieldName);
if (prop.validators.length > 0) {
var context = { entity: entityAspect.entity, property: prop, propertyName: fieldName };
if (entityAspect._validateProperty(value, context)) {
return true;
}
return false;
}
}
}
}
There is no separate method to validate a complex type because the validation results are all part of the 'parent' entity. Complex type properties are considered part of the entity, not independent entities.
What you can do is call validateProperty on the 'complex' property of the parent entity.

Reference an object, based on a variable with it's name in it

I'm looking for a way to reference an object, based on a variable with it's name in it.
I know I can do this for properties and sub properties:
var req = {body: {jobID: 12}};
console.log(req.body.jobID); //12
var subProperty = "jobID";
console.log(req.body[subProperty ]); //12
var property = "body";
console.log(req[property][subProperty]); //12
is it possible for the object itself?
var req = {body: {jobID: 12}};
var object = "req";
var property = "body";
var subProperty = "jobID";
console.log([object][property][subProperty]); //12
or
console.log(this[object][property][subProperty]); //12
Note: I'm doing this in node.js not a browser.
Here is an exert from the function:
if(action.render){
res.render(action.render,renderData);
}else if(action.redirect){
if(action.redirect.args){
var args = action.redirect.args;
res.redirect(action.redirect.path+req[args[0]][args[1]]);
}else{
res.redirect(action.redirect.path);
}
}
I could work around it by changing it to this, but I was looking for something more dynamic.
if(action.render){
res.render(action.render,renderData);
}else if(action.redirect){
if(action.redirect.args){
var args = action.redirect.args;
if(args[0]==="req"){
res.redirect(action.redirect.path+req[args[1]][args[2]]);
}else if(args[0]==="rows"){
rows.redirect(action.redirect.path+rows[args[1]][args[2]]);
}
}else{
res.redirect(action.redirect.path);
}
}
Normally it's impossible to reference an object by its name. But since you have only two possible candidates...
var args, redirect_path = '';
if(args = action.redirect.args) {
try {
redirect_path = ({req:req,rows:rows})[args[0]][args[1]][args[2]];
} catch (_error) {}
}
res.redirect(action.redirect.path + (redirect_path || ''));
I'm using inline object {req:req,rows:rows} as a dictionary to lookup for args[0] value.
I wrapped the whole construction with try ... catch, because it's dangerous. For example, passing anything except 'req' or 'rows' as args[0] will result in an exception being thrown.
I also moved res.redirect outside of if to clarify the code.
Update
It's also possible to use args array with arbitrary length. But to do so you'll need to loop through args array:
var branch, redirect_path;
if (action.redirect.args) {
try {
branch = { req: req, rows: rows }
action.redirect.args.forEach(function(key) {
branch = branch[key];
});
if ('string' === typeof branch) {
redirect_path = branch;
}
} catch (_error) {}
}
res.redirect(action.redirect.path + (redirect_path || ''));
A added 'string' === typeof branch check to ensure that the resulting value is a string.

JavaScript: Not Calling Constructor Function

Can someone shed some light as to why this doesn't work the way I think it should (or what I'm overlooking).
function Pane(data) {
var state = {
show: function(data) {
var pane = document.querySelector('.pane[data-content='+data.target+']');
pane.classList.add('active');
},
hide: function(data) {
var pane = document.querySelector('.pane[data-content='+data.target+']');
var paneSibling = $(pane.parentNode.childNodes);
paneSibling.each(function(sibling) {
if(check.isElement(sibling)) {
var isActive = sibling.classList.contains('active');
if(sibling != pane && isActive) {
sibling.classList.remove('active');
};
};
});
}
}
return state;
}
So I can console log Pane(arg).show/hide and it'll log it as a function, so why is it when I call Pane(arg).show it doesn't do anything? The functions in the object work (outside of the constructor function in their own functions).
The function is returning the state object, so it will never return the constructed object, even when used with new. Since state contains those methods, you can just call the function and immediately invoke one of the methods on the returned object.
Now, if you're expecting show and hide to automatically have access to data via closure, it's not working because you're shadowing the variable by declaring the method parameters. You can do this instead:
function Pane(data) {
var state = {
show: function() {
var data = data || arguments[0];
var pane = document.querySelector('.pane[data-content='+data.target+']');
pane.classList.add('active');
},
hide: function() {
var data = data || arguments[0];
var pane = document.querySelector('.pane[data-content='+data.target+']');
var paneSibling = $(pane.parentNode.childNodes);
paneSibling.each(function(sibling) {
if(check.isElement(sibling)) {
var isActive = sibling.classList.contains('active');
if(sibling != pane && isActive) {
sibling.classList.remove('active');
};
};
});
}
}
return state;
}
Then you can use it like this:
Pane({}).show();
Or like this:
var p = Pane();
p.show();
Or force a new argument when needed:
p.show({foo:'bar'});
You are overriding the original argument in each function.
So what you are doing is to find elements with the attribute data-content='undefined'
This obviously doesn't work.
So to fix this you should just remove the data argument in the show/hide function.
Here is a plnkr showing the problem and fix.

How can I pass results from a callback via an object?

I am performing a Google local search, and wish to return the lat/long via an object.
The Google search itself works fine.
When inspected (using console.log or alert()) in the object itself, the results field appears to be populated OK.
However, when inspecting the instance of the object (instantiated before running the callback) the result is blank. I'm aware I don't need the accessor function - the end result is the same either way.
Is there something fundamental missing here? Thanks!
function GeoSearch() {
this.results = [];
this.searchComplete = function(localSearch) {
if(localSearch.results[0]) {
var resultLat = localSearch.results[0].lat;
var resultLng = localSearch.results[0].lng;
this.results = localSearch.results[0].lat;
}
}
this.getResults = function() {
return this.results;
}
}
function populateCoords(postcode) {
var localSearch = new google.search.LocalSearch();
var gs = new GeoSearch();
localSearch.setSearchCompleteCallback(gs, gs.searchComplete, [localSearch]);
localSearch.execute(postcode + ", UK");
alert(gs.getResults());
}
When you reference the function gs.searchComplete, you're detaching the method from the object it belongs to. Switch it to function () { gs.searchComplete(); }

Categories

Resources