AngularJS Error: Cannot set property 'UserData' of null - javascript

I run the following AngularJS code from a partial page:
$scope.$parent.UserData = {};
$http.get('http://.../GetUserData/').
then(function (result) {
$scope.$parent.UserData = result.data;
}, function errorCallback(error) {
console.log(error);
});
I know that $scope.$parent is not null and I know that result.data returns an object with multiple properties. Not sure why I am getting this error since $scope.$parent is not null
The above partial page is displayed in ui-view on index page. Here is html from index page:
<body ng-controller="BaseCtrl">
<nav>
</nav>
<div class="" ui-view>
//partial pages displayed here
</div>
<!-- Modal Structure -->
<div id="modal1" class="modal">
<div class="modal-content">
<h4>Heading</h4>
<div class="row">
<table>
<tr>
<td>ID:</td>
<td>{{UserData.ID}}</td>
</tr>
<tr>
<td>Person name:</td>
<td>{{UserData.Name}}</td>
</tr>
</table>
</div>
</div>
<div class="modal-footer">
<button ng-click="closeModal()" class="modal-action modal-close waves-effect waves-green btn-flat">Close</button>
</div>
</div>
</body>

I think you have not defined $scope.$parent. So define it first.
$scope.$parent = {};
$scope.$parent.UserData = {};
$http.get('http://.../GetUserData/').
then(function (result) {
$scope.$parent.UserData = result.data;
}, function errorCallback(error) {
console.log(error);
});
Optimal syntax for object of objects.
$scope.$parent = {UserData:{}};

could please try this
$http.get('http://.../GetUserData/').
then(function (result) {
$scope.$parent.UserData = {};
$scope.$parent.UserData = result.data;
}, function errorCallback(error) {
console.log(error);
});

After a while of trying out different things I finally came up with the solution. Here is what worked for me:
$scope.$parent.UserDataColl = [];
$http.get('http://.../GetUserData/').
then(function (result) {
$scope.UserDataColl.push(result.data);
}, function errorCallback(error) {
console.log(error);
});

Related

Writing the event handlers for next button onclick for datatable in an angularjs controller

I am trying to write an event handler for page change in a datatable. following is the existing code.. the libraries are included in a baselayout for following code..
DefaultView.cshtml
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-6 col-xs-6 pageheading">
<h1>
<small>AMS Default</small>
</h1>
</div>
</div>
<hr />
<br />
<div class="row">
<div class="col-lg-12">
<table dt-options="dtOptions" datatable dt-columns="dtColumns"
class="table table-striped table-bordered dt-responsive">
<thead>
<tr>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
</table>
</div>
</div>
#section CommonScripts{
<script src="~/Angular/Areas/Common/Controllers/DefaultController.js"></script>
<script src="~/Angular/Areas/Common/Services/DefaultService.js"></script>
}
Defaultcontroller.js
AMSApp.controller('DefaultController', ['$rootScope', 'DefaultService', 'DTOptionsBuilder', 'DTColumnBuilder',
function ($rootScope, DefaultService, DTOptionsBuilder, DTColumnBuilder) {
var self = this;
this.Users = {};
this.GetAllUsers = function () {
$rootScope.CloseAlerts();
DefaultService.GetAllUsers().success(function (result) {
self.Users = result;
self.loadd();
}).catch(function (error) {
$rootScope.ErrorMsg = "OOPS some thing went wrong. Please try again.";
});
}
this.GetAllUsers();
this.loadd = function () {
$rootScope.dtColumns = [
DTColumnBuilder.newColumn('DisplayName').withTitle('UserName'),
DTColumnBuilder.newColumn('IsSNA').withTitle('IsSNA'),
DTColumnBuilder.newColumn('IsAdmin').withTitle('IsAdmin'),
DTColumnBuilder.newColumn('IsDownloadPermitted').withTitle('DownloadPermitted')
];
$rootScope.dtOptions = DTOptionsBuilder.newOptions()
.withOption('data', self.Users)
.withDisplayLength(10);
}
}]);
/*
Button Click handler:
$("#customerSearchButton").on("click", function (event) {
$.ajax({
url: "",
type: "post",
data: { searchText: searchText }
}).done(function (result) {
Table.clear().draw();
Table.rows.add(result).draw();
}).fail(function (jqXHR, textStatus, errorThrown) {
// needs to implement if it fails
});
}
*/
DefaultService.js
AMSApp.service('DefaultService', function ($http) {
this.GetAllUsers = function () {
return $http.get('/Common/User/GetAllUsers');
}
});
I tried several versions like in the above-commented code.. but I need something like following in the controller.
/*need something like this*/
DTOptionsBuilder.on('page.dt', function () {
var info = table.page.info();
console.log("hey i got eexecuted");
$('#pageInfo').html('Showing page: ' + info.page + ' of ' + info.pages);
});
firstly is it possible? - if not what are other alternatives?
Note: I prefer not to give an id to the table.

$http.get unable to fetch data from SpringBoot controller

I am creating an application which will run queries on my store's database, based on what the user enters on the webpage. I have successfully created the backend method. And it successfully returns the response. But I am unable to retrieve the data and display it on my webpage in the form of a dynamic table. I am a bit new to AngularJS, so please bear with me, but any help is appreciated.
StoreController.java
#RequestMapping(value = "/runQuery", method = RequestMethod.GET)
public List<Map<String, Object>> runQuery(#RequestParam(value="query", defaultValue="* FROM items") String statement, Model model) {
List<Map<String, Object>> answer = storeService.executeUserQuery(statement);
model.addAttribute("resultList", answer);
return answer;
}
I tried to model my controller in such a way that it can dynamically take the data received from the Java controller and assign it to the $scope variable.
app.module.js
(function(){
'use strict';
angular.module('app', []);
})();
store.controller.js
angular
.module('app').controller('StoreController', ['$scope','StoreService','StoreController','$q', function ($scope,StoreService, StoreController, $q) {
$scope.runQuery = function () {
StoreService.runQuery($scope.statement)
.then (function (data){
$scope.rows = response.data;
$scope.cols = Object.keys($scope.rows[0]);
},
function error(response){
if (response.status == 404){
$scope.errorMessage = response.data[0];
}
else {
$scope.errorMessage = 'Error displaying result user!';
}
});
}
}
]);
app.service('StoreService',['$http', function ($http,$q) {
this.runQuery = function runQuery(statement){
return $http({
method: 'GET',
url: 'http://localhost:8080/runQuery/',
params: {statement:statement},
headers: 'Accept:application/json'
}).then( function(response){
return reponse.data;
});
}
index.html
<body data-ng-app="app" data-ng-controller="StoreController">
<div class="container">
<form th:action="#{/logout}" method="get">
<button class="btn btn-md btn-danger btn-block"
style="color: #fff; background-color: #e213a2; border-color: #c3c2c0;"
name="registration" type="Submit">Logout</button>
</form>
<div class="panel-group" style="margin-top: 40px">
<div class="panel panel-primary">
<div class="panel-heading">
<span th:utext="${userName}"></span>
</div>
<div>
<form name="queryForm" method="get" data-ng-submit="runQuery()">
<div class="panel-body">
<h3 id="queryLabel">Select Query:</h3>
<textarea id="query" wrap="soft"
placeholder="Please do not enter SELECT with your query, it's added automatically!!" data-ng-model="statement"></textarea>
<button type="submit">Run Query</button>
</div>
</form>
<div class="panel-body" id="results">
<h3 id="queryLabel">Result:</h3>
<table border="1">
<tr>
<th data-ng-repeat="column in cols">{{column}}</th>
</tr>
<tr data-ng-repeat="row in rows">
<td data-ng-repeat="column in cols">{{row[column]}}</td>
</tr>
</table>
</div>
</div>
<div>
<p class="admin-message-text text-center" th:utext="${adminMessage}"></p>
</div>
</div>
</div>
</div>
</body>
The table on the html page, works because I received it from this link
http://jsfiddle.net/v6ruo7mj/1/
But it's not populating the tables with the data received from my backend controller method. I do not have any entities as this is just querying an existing database, so I need not to add any entities.
The issue probably is this line here in the service callback within your controller:
.then (function (data){
$scope.rows = response.data;
// ...
}
try with:
.then (function (data){
$scope.rows = data;
// ...
}
You already return the responses data in your service when calling:
}).then( function(response){
return reponse.data;
});
Aside from your question I should mention that your Spring controller seems to be vunerable to SQL injection. It's in general not a good idea to allow the user to access your database directly. Although I don't know how your StoreService on the backend is implemented. But it seems as if an attacker could easily send a HTTP call to your endpoint and drop your database.
You have a typo in the runQuery function:
app.service('StoreService',['$http', function ($http,$q) {
this.runQuery = function runQuery(statement){
return $http({
method: 'GET',
url: 'http://localhost:8080/runQuery/',
params: {statement:statement},
headers: 'Accept:application/json'
}).then( function(response){
̶r̶e̶t̶u̶r̶n̶ ̶ ̶r̶e̶p̶o̶n̶s̶e̶.̶d̶a̶t̶a̶;̶
return response.data
});
}
}]);

How to make saved object immediately appear in a ng-repeat?

JS:
$scope.addPano = function () {
var Pano = AV.Object.extend("Panorama"),
pano = new Pano()
var json = {
'name': 'test3',
'index': 0,
'Type': 'real',
'version': 0,
'buildingCode': $scope.buildingId
}
pano.save(json, {
success: function(object) {
console.log('PANO: ', object)
$scope.building.pano.push(json)
$scope.$digest()
},
error: function(object, error) {
console.log('Failed to create new object, with error message: ' + error.message);
}
})
}
HTML:
<div ng-repeat="pano in building.pano">
<p><strong>{{pano.name}}</strong></p>
<div ng-repeat="panodata in pano.panoData">
<p>{{panodata.name}}</p>
</div> <a class="btn btn-default" href="javascript:;" ng-click="addPanodata(pano.objectId)">Add panodata</a> </div> <a class="btn btn-default btn-lg" href="javascript:;" ng-click="addPano()">Add pano</a>
</div>
Right now the only way to make it appear is with:
$scope.building.pano.push(json)
$scope.$digest()
I thought Angular did this automatically?
I think you can try this type But In your code either you reload data after save method calling successfully then you can easily appear easily..
function myctrl($scope){
$scope.data =[{name:'abc'}];
$scope.pushdata = function(name){
$scope.data.push({name});
$scope.name ='';
}
}
<html ng-app=''>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
</head>
<body ng-controller='myctrl'>
<input type='text' name='name' ng-model='name'/>
<button name='clickme' type=submit ng-click='pushdata(name)'>save</button>
<div ng-repeat='obj in data'>
{{obj.name}}
</div>
</body>
</html>
The official way to do this is to write your pano service to support angular. So where you call the success callback in the service:
.factory('pano', function() {
return {
save: function(x, options) {
setTimeout(function() {
options.success(123);
}, 1000);
}
};
});
You should wrap it in a $scope.$apply so angular has an opportunity to run dirty-checking:
.factory('pano', function($rootScope) {
return {
save: function(x, options) {
setTimeout(function() {
$rootScope.$apply(function() {
options.success(123);
});
}, 1000);
}
};
});
The same applies for the error handling callback.
Note: The builtin angular services, like $http, $q, $timeout do this automatically.

Why is angular-promise-tracker not working for me?

I've installed angular-promise-tracker and I think I'm close to getting it working. The problem I'm having is that the "loading" text isn't showing. The data is fetched and does show when outputting it to the console.
So it appears that ng-show="loadingTracker.active()" isn't working. I can't see what I'm doing wrong with this.
Any help with this would be sincerely appreciated - as always :)
Here's my code:
HTML
<button ng-controller="weatherCtrl"
ng-model="hotel"
class="btn btn-default"
ng-click="loadWeather(hotel, $index)">
{{buttonText}} more</button>
<div collapse="isCollapsed">
<div class="well well-lg more-detail">
{{hotel.Description}}
<br /><br />
<div>
<div class="my-super-awesome-loading-box"
ng-show="loadingTracker.active()">
Loading..
</div>
</div>
</div>
</div>
JS
.controller('weatherCtrl', function ($scope, weather, $timeout, promiseTracker){
$scope.loadingTracker = promiseTracker();
$scope.buttonText= 'Load'
$scope.loadedHotelDetails=[];
$scope.loadWeather = function(hotel, index) {
// console.log('loadWeather')
weather.get({tracker: $scope.loadingTracker}, function (data){
console.log(data)
$scope.loadedHotelDetails.push(index)
})
})
angular.module('weather', [])
.factory('weather', function($http) {
var weather = {};
weather.get = function(params, callback) {
$http.get('/php/weather.php', {params: {tracker: params.tracker, page: params.page}}).success(function(data) {
callback(data);
});
};
return weather;
});
I've never used this module, but from the examples on github, I think you're supposed to call it like this in weather:
weather.get = function(params, callback) {
$http.get('/php/weather.php', {tracker: params.tracker, page: params.page}).success(function(data) {
callback(data);
});
};
Got it sorted, this is the code I needed:
.factory('weather', function($http) {
var weather = {};
weather.get = function(params) {
return $http.get('/php/weather.php', {tracker: params.tracker, page: params.page});
};
return weather;
});

How to process an array with AngularJS?

I have an API returning the following simple JSON array:
[
"efd98ad-first_key",
"100eb0a-second_key"
]
I am trying to render this as a table with Angular:
<div name="listkeys" class="container">
<div class="starter-template">
<div ng-bind-html="message"></div>
<table class="table table-striped table-bordered table-condensed sortable" ng-init="getKeys()">
<tr>
<th>bucket</th>
</tr>
<tr ng-repeat="bucket in buckets">
<td>{{bucket}}</td>
</tr>
</table>
</div>
</div>
JS:
var app = angular.module('flipDaSwitch', ['ngSanitize']);
app.controller('ListKeys', function($scope, $http) {
$scope.getKeys = function() {
$http.get('/api/keys').
success(function (data) {
$scope.response = data;
}).
error(function (data){
$scope.response = {}
});
};
});
It does not do anything but throwing an "Uncaught object" error and that is it.
How could I debug why it is failing?
You are storing the values in $scope.response, but you are using $scope.bucket at the ng-repeat:
$scope.getKeys = function() {
$http.get('/api/keys').
success(function (data) {
$scope.buckets= data;
}).
error(function (data){
$scope.buckets= {}
});
};
It looks like you do not have a scope item called buckets. I'd expect to see:
$scope.buckets = data
Inside the success callback.

Categories