306_expandable_grid - cannot read the property of 'data' undefined - angularjs

i am working on ui-grid and 306_expandable_grid , i have used the exact code as in the doc but i am facing a problem with an error .
app.js
$http.get('resources/data/title2.json')
.success(function(data){
console.log(data);
console.log(data[0].Data);
console.log(data.length);
for(i = 0; i < data[i].length; i++){
data[i].subGridOptions = {
columnDefs: [
{name:"Title" },
{name:"Jan-10" },
{name:"Feb-10"},
{name:"Mar-10" },
{name:"Apr-10" },
{name:"May-10" },
{name:"Jun-10" },
{name:"Jul-10" },
{name:"Aug-10" },
{name:"Sep-10" },
{name:"Oct-10" },
{name:"Nov-10" },
{name:"Dec-10" }
],
data: data[i].Data
}
}
// $scope.subGridOptions.data = data;
$scope.gridOptions.data = data;
// $scope.title = data[0].Title;
});
externalHtmlFile.html
<div ui-grid="row.entity.subGridOptions" style="height:150px;"></div>
this is the error that i am stuck with
TypeError: Cannot read property 'data' of undefined
at new <anonymous> (http://localhost/ng-Grid/resources/scripts/ui-grid-unstable.js:2883:41)
at Object.e [as invoke] (http://localhost/ng-Grid/resources/scripts/angular.min.js:36:456)
at E.instance (http://localhost/ng-Grid/resources/scripts/angular.min.js:75:118)
at http://localhost/ng-Grid/resources/scripts/angular.min.js:58:276
at r (http://localhost/ng-Grid/resources/scripts/angular.min.js:7:408)
at M (http://localhost/ng-Grid/resources/scripts/angular.min.js:58:260)
at http://localhost/ng-Grid/resources/scripts/angular.min.js:65:412
at http://localhost/ng-Grid/resources/scripts/angular.min.js:109:276
at h.$eval (http://localhost/ng-Grid/resources/scripts/angular.min.js:123:139)
at h.$digest (http://localhost/ng-Grid/resources/scripts/angular.min.js:120:220)
when i click on the plus icon , the error occurs ... i could not find out a solution that i can understand . please help

First, make sure that you initialize $scope.gridOptions outside of $http.get success callback. Only add the $scope.gridOptions.data[i].subGridOptions to $scope.gridOptions inside the success callback. Reference:
You can't define the grid options in the success call. You need to define them on the scope in your controller and then set the data or column definitions, etc... from the success call.
Second, make sure that the controller of the grid/page doesn't have any kind of initialization parameter-dependent redirects. I faced the same error message generated because of the following piece of code I had on the page:
if (typeof clientcode === 'string' && clientcode !== '') {
var payload = {
clientcode : storedClientcode
}
} else {
$location.path('/');
}
The idea here was to check if the storedClientcode was provided by the calling page (via a shared app root service), and if not, redirect to the application home. But the ui-grid apparently makes separate sub-calls to the page its on, and those sub-calls of course do not provide the data I was looking for with my code, and so the redirect occurred behind the scenes for those calls. No errors (other than what you also saw) were produced, and no data showed up in the grid. This took me some time to figure out (I'm fairly new with AngularJS, and this was the first application of ui-grid for me).. hopefully this will help someone, even if it doesn't resolve this question.

Related

Getting Error while waiting for Protractor to sync with the page: "both angul arJS testability and angular testability are undefined

I am trying to run a Protractor Test using PageObjectModel (module.exports mechanism).
My HomePageObjects.js is like below -
//Get the page objects to spec files in the form of key-value pair
/*module.exports.Homepage=
{
Name:element(by.name('name')),
Email:element(by.name('email')),
Password:element(by.id("exampleInputPassword1")),
Checkbox: element(by.css("input[id='exampleCheck1']")),
// element(by.cssContainingText("[id='exampleFormControlSelect1'] option", "Female")).click(); //One way to select a value
Gender:element(by.css("select[id='exampleFormControlSelect1']")).click().element(by.css("select[id='exampleFormControlSelect1']>option:nth-child(2)")), //Another way
// to select a value
EmploymentStatus:element(by.id("inlineRadio1")),
SubmitBtn:element(by.buttonText("Submit")),
Success:element(by.css("div[class*='success']"))
};*/
function HomePage1()
{
this.Name=element(by.name('name'));
this.Email=element(by.name('email'));
this.Password=element(by.id("exampleInputPassword1"));
this.Checkbox= element(by.css("input[id='exampleCheck1']"))
// element(by.cssContainingText("[id='exampleFormControlSelect1'] option", "Female")).click(); //One way to select a value
this.Gender=element(by.css("select[id='exampleFormControlSelect1']")).click().element(by.css("select[id='exampleFormControlSelect1']>option:nth-child(2)")); //Another way
// to select a value
this.EmploymentStatus=element(by.id("inlineRadio1"));
this.SubmitBtn=element(by.buttonText("Submit"));
this.Success=element(by.css("div[class*='success']"));
}
Homepage1 = new HomePage1();
module.exports={
Homepage1
}
When I am trying to execute the spec (which is below), I am getting error.
I have tried with browser.waitForAngularEnabled(false); but of no avail.
describe('Submit Form', function(){
var obj = require("./HomePageObjects.js"); // Access the objects from HomePageObjects.js
it('Test Submit Form', function(){
browser.get("https://qaclickacademy.github.io/protocommerce/");
obj.Homepage1.Name.sendKeys("Prabodh");
});
})
Can anyone please help me?
Error -
Message:
Error: Error while waiting for Protractor to sync with the page: "both angul
arJS testability and angular testability are undefined. This could be either be
cause this is a non-angular page or because your test involves client-side navig
ation, which can interfere with Protractor's bootstrapping. See http://git.io/v
4gXM for details"

Trying to bind in ng-init a value. This value was set afler model loading, and 2 ajax calls

I explain myself,
The application i'm making right now come from a derivative of phonegap. I must absolutely waiting ajax answer to set de ng-init. I know i can do something like this ng-init = "ng-model = arr[0]" or i can use a variable for le position of the array like ng-init = "ng-model = arr[position]". That is simple in most case, but me because i'm working on a derivative phonegap i must call my function from a focus method with an ajax call, plus waiting after the result of another ajax call. See what i mean:
HTML select code:
<select id="usSelect" class="geotabFormEditField" ng-init="usCycle = usCyclesArr[usPos]" ng-model="usCycle" ng-options="x.descEn for x in usCyclesArr" ng-change="usSel()"}></select>
Function where i call my angular function to define which option must be selected. I must absolutely call it in this function.
focus: function (freshApi, freshState) {
freshApi.getSession(session => {
database = session.database;
freshApi.call('Get', {
typeName: 'User',
search: {
name: session.userName
}
}, function(user){
lang = user[0].language;
glScope.getHosRules(database);
}, function(){
//Oops can't get user
});
});
},
function called is getHosRule.
The angular array:
$scope.usCyclesArr = [{cycleId: 'America8Day', descEn: 'USA Property 70-hour/8-day', descFr: 'Propriété É.-U. 70 heures/8 jours'}, {cycleId: 'America7Day', descEn: 'USA Property 60-hour/7-day', descFr: 'Propriété É.-U. 60 heures/7 jours'}, {cycleId: 'America7DayBig', descEn: 'USA Property 60-hour/7-day (16-hour exemption)', descFr: 'Propriété É.-U. 60 heures/7 jours (exemption de 16 heures)'}, {cycleId: 'America7DayNo34h', descEn: 'USA Property 60-hour/7-day without 34-hour reset', descFr: ''}, ...];
function to get which option must be selected:
$scope.getHosRules = function(dat) {
console.log(dat, url);
$http({
method: 'GET',
url: $scope.urlPath + 'borderCross/' + dat + '/getHosRules',
responseType: 'json',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
}).then(function successCall(response) {
//console.log(response.data);
for(var i = 0; i < $scope.usCyclesArr.length; i++) {
//console.log($scope.usCyclesArr[i].cycleId);
if($scope.usCyclesArr[i].cycleId === response.data[0].us_id) {
$scope.usPos = i;
}
}
}, function errorCall() {
console.log('Unexpected error');
});
}
The problem is usPos get is value after ng-model is loaded and i must waiting for ajax answer, so it desn't working. I tried ng-init="{{usCycle = usCyclesArr[usPos]}}" It seem working but an error appear in the console and i can't take the risk on a professional app. So Anybody knows how can i bind usPos variable ?
From what I can understand from your question, you need to set the value of $scope.usCycle which will be shown as the selected value of dropdown.
Rather than setting the value in ng-init, why are you not setting in for loop:
for(var i = 0; i < $scope.usCyclesArr.length; i++) {
//console.log($scope.usCyclesArr[i].cycleId);
if($scope.usCyclesArr[i].cycleId === response.data[0].us_id) {
$scope.usCycle = usCyclesArr[i]; // <-- directly assigning value
}
}
Few points I would like to highlight:
You are facing issues because your ng-init works with AngularJS lifecycle where as your Business logic is triggered from focus function which is not at all connected with AngularJS. So, its a bad choice to mix code like this. To provide better UX, you can use spinner to make the user wait unless the $scope.usCycle value is assigned.
Rather than iterating through entire loop of for(var i = 0; i < $scope.usCyclesArr.length; i++) , you can break break the loop once you find the value. It will save extra looping cycles.
I found the way myself and it's simple. Refreshing my ng-model with the simple code below and removing ng-init attribute in html file.
$scope.usCycle = $scope.usCyclesArr[$scope.usPos];
Dropdown take right position.
Of course like Vivek said, breaking the loop when position is found is better.

I'm not calling $apply explicitly but still get Error: [$rootScope:inprog] $apply already in progress

In a angular factory I have a method to create a new item, which has a connection to a user and a price to add to that users "items" array (like a shopping cart). So I have to see if the user is present in my the local users array if not then on the server and if not then create the user.
Code looks like this:
var saveItem = function (item) {
var user = filterUserById(item.ownerId);
if (user) {
user.createItem(item);
} else {
repository.getUserById(item.ownerId).then(
function (serverUser) {
var userViewModel = repository.getUserViewModel(serverUser);
userViewModel.createItem(item);
users.push(userViewModel);
}
, function () {
user = {
id: item.ownerId,
items: [
createItemDto(item)
]
};
repository.createUser({ id: user.id }, user);
users.push(repository.getUserViewModel(user));
});
}
};
No matter which of the "cases" occurs (user was found localy, on the server or was created and added) I get an error:
Error: [$rootScope:inprog] $apply already in progress
http://errors.angularjs.org/1.3.0-beta.18/$rootScope/inprog?p0=%24apply
I recon this may have to do with the fact that I'm using resources in my repository, but I don't think resource should (since it's a part of angular..). Here's the user.createItem method, code:
user.createItem = function (item) {
var resource = userResource
, itemDto = createItemDto(item)
, command = [{
Type: 'add',
Name: 'items',
Value: itemDto
}];
resource.createItem({ id: item.ownerId }, command);
this.items.push(itemDto);
};
Y U NO WERK!? PLS HLP! :'(
P.S. I don't have any explicit calls to apply, compile or digest anywhere in my code.
Found the problem! I had put a small code line to set focus on the correct input after the item was added and form was emptied. This consisted of a
$('selector').focus();
This was colliding with digest cycle... Solution:
$timeout($('selector').focus());
Try wrapping your call to user.createItem(item) in a $timeout function:
$timeout(function() {
user.createItem(item);
}, 0);
It's possible you could be triggering some other call to $scope.$apply() some other way.
Alternatively, try using $scope.$evalAsync(function())
Here's some good info: inprog

_.bindAll(this) and Uncaught TypeError: Cannot read property 'idAttribute' of undefined in backbone-relation.js

I have two models (User and Task) which are instances of Backbone.RelationalModel.
The relation about these two models is the following:
// Task model
var Task = Backbone.RelationalModel.extend({
relations: [
{
type: 'HasOne',
key: 'user',
relatedModel: User
}
],
urlRoot: 'someUrl'
});
Then I have one collection which code looks like this:
var FollowerCollection = Backbone.Collection.extend({
initialize: function () {
_.bindAll(this);
}
model: User
});
var User = Backbone.RelationalModel.extend({
});
When I make a fetch on FollowerCollection I get the following error:
Uncaught TypeError: Cannot read property 'idAttribute' of undefined
on the line 1565 of backbone-relation.js of backbone-relation version 0.5.0
Here a piece of code of backbone-relation.js
if ( !( model instanceof Backbone.Model ) ) {
// Try to find 'model' in Backbone.store. If it already exists, set the new properties on it.
var existingModel = Backbone.Relational.store.find( this.model, model[ this.model.prototype.idAttribute ] );
The problem is related to _.bindAll(this) because if I comment it, it works properly.
Why? Any ideas?
Removing the _.bindAll does work.
It's a shame, because it's a really handy function. It must interact with some part of Backbone badly. I'm on v9.10
I use this method all the time, and issues only come up sometimes (like when you want to do a bulk add to a collection).
For me, The problem was in this Backbone.js method:
// Get a model from the set by id.
get: function(obj) {
if (obj == null) return void 0;
this._idAttr || (this._idAttr = this.model.prototype.idAttribute);
return this._byId[obj.id || obj.cid || obj[this._idAttr] || obj];
},
The code fails at this.model.prototype because prototype is undefined. What? Ya. For reals.
The problem is that when _.bindAll is called, it binds all properties of the collection, as #jakee says. This seems to include Collection.model, which is a bug I think.
The solution is to bind individual methods until this is fixed.
There's an existing, but closed issue on github: https://github.com/documentcloud/backbone/issues/2080
Seems like the current maintainers don't like the method, but I don't understand why.
Like my project is really big I had to create my custom bindAll. Here you have the code, it works with the lastest versions.
I bind all the properties of the instance "this" except the ones that has prototype with properties, like this.model in a Collection
https://gist.github.com/patrixd/8025952
//bindAll from underscore that allows 1 argument to bind all the functions from the prototype,
//or if there are more arguments they will be the only binded
_.originalBindAll = _.bindAll;
_.bindAll = function (that) {
var funcs = Array.prototype.slice.call(arguments, 1),
validKeys = [], fn;
if (funcs.length == 0) {
for (var i in that) {
fn = that[i];
if (fn && typeof fn == "function" && (!fn.prototype ||
_.keys(fn.prototype).length == 0))
validKeys.push(i);
}
_.originalBindAll.apply(_, [that].concat(validKeys));
}
else
_.originalBindAll.apply(_, arguments);
};

Sencha scope issue

I've completely rewritten my question to hopefully better reflect what I am trying to do here. Thank you guys so much for your help so far.
I have a file called en.js, which holds this code:
Ext.apply(Ext.locale || {}, {
variable: 'great success!'
});
Here's my index.js setup code:
Ext.setup({
tabletStartupScreen: 'tablet_startup.png',
phoneStartupScreen: 'phone_startup.png',
icon: 'icon.png',
glossOnIcon: false,
onReady: function() {
Ext.locale = {};
var headID = document.getElementsByTagName("head")[0],
newScript = document.createElement('script');
newScript.type = 'text/javascript';
newScript.src = 'en.js';
headID.appendChild(newScript);
loginPanel = new login.Panel();
}
});
login.Panel is an extension of the Sencha panel class using Ext.extend.
The 'en.js' script is added to the header correctly. I don't have it in the index.html file because once this problem is solved there will be several files that could be loaded, depending on the output of a function. That's why I need to add the script to the header in the onReady function, and not in the index.html file itself.
Once the script has been added it loads "variable: 'great success'" into Ext.locale,
Yet my problem currently lies within login.Panel(), which is an extension of the Sencha panel class using Ext.extend.
Currently, there is a button in the panel.
When I put this in the button's handler:
console.log(Ext.locale.variable)
it returns the string "great success",
yet when I try to set the button's text like this:
text:Ext.locale.variable,
I get the error
Uncaught TypeError: Cannot read property 'variable' of undefined
I'm guessing I have a scope issue here, since console.log() and alert() can both access Ext.locale, but trying to use it to construct the form gives me the undefined error.
Any help would be greatly appreciated.
Thank you!
it sounds like you are defining Ext.locale from your script early on... then later in onReady you are overwriting it as Ext.locale = {}
onReady will run after all your other scripts have been loaded.
Why not move your initialisation code for locale into onReady insted of your = {} line
This will add three properties and their values to the receiving object.
Ext.apply(receivingObject, {
property1: 'value1',
property2: 'value2',
property3: 'value3'
});
Here also is the Sencha documentation on the Ext.apply method:
http://dev.sencha.com/deploy/touch/docs/source/Ext.html#method-Ext-apply
As for accessing the isReady property, you could do something like if(someExtObj.isReady), but you may be more interested in using the onReady method...
Ext.setup({
onReady: function() {
// your setup code
}
});

Resources