Cannot access object data with ng-repeat - angularjs

I have an app using routing and I'm working with my first route. The view loads correctly, and I'm able to access data objects in the controller linked to the view, but not the objects created in a function in the controller. Here are code snippets:
html:
<div>
<label>Select Table : </label>
<select ng-init="permits.lookups.selectedLookup = lookupLists[0].list" ng-model="permits.lookups.selectedLookup" ng-options="lookupList.list as lookupList.desc for lookupList in lookupLists" ng-change="populateLookup(permits.lookups.selectedLookup)"></select>
Selected lookup: {{permits.lookups.selectedLookup}}
<table>
<tbody>
<tr><td>first row</td></tr>
<tr ng-repeat="column in columns"><td>{{column.name}}</td></tr>
<tr><td>last row</td></tr>
</tbody>
</table>
</div>
js:
(function() {
var app = angular.module('lookups',[]);
app.controller('UpdateLookups', function($scope, $http) {
var lookups = this;
$scope.lookupLists = [
{list : "0", "desc" : "--Select List--"},
{list : "del_type", "desc" : "Delivery Type"},
{list : "pay_type", "desc" : "Payment Types"},
{list : "trans_type", "desc" : "Transaction Type"}
];
$scope.selectedLookup = $scope.lookupLists[0].list;
$scope.populateLookup = function(lookup) {
$http({
url : <some URL>
dataType : "json",
method : "POST",
data : "action=3&lookup="+lookup,
headers : {"Content-Type" : "application/x-www-form-urlencoded; charset=utf-8"}
}).success(function(data) {
if ( angular.isArray(data.columns)) {
lookups.columns = data.columns;
} else {
lookups.columns = [data.columns];
}
}).error(function(error){
alert("There was an error");
});
};
});
})();
Upon loading, the select options are correctly initialized with the data in the lookupLists object, and when the user changes the selected option, the ng-change directive successfully triggers the populateLookup function, which successfully populates the lookups.columns object. The problem is that I'm having difficulty binding the lookups.columns object with my ng-repeat directive in my table. I've tried to reference the object using columns, lookups.columns, and permits.lookups.columns, yet I cannot seem to access it.
I tried to do something similar in my main controller, and after researching, I found that if I created a variable and assigned "this" to it, then referenced that variable when creating my object, it worked - my assumption is that the assignment of "this" effectively allows the function to assign objects in a scope outside of its own scope. I tried to do that here by creating lookups, but that doesn't seem to be helping here. I can see that lookups.columns is indeed created, but it is not in the $scope of the controller. I'm just learning AngularJS (please be gentle) and still trying to wrap my head around all the binding and scope limitations. I'm guessing that my answer is to build a service/factory and inject it, but when I try to do that based on all of the examples I've seen, it breaks the parts that I have working, so I come back to this starting point, where at least everything else works.

Perhaps you forget '$scope' in front of 'column' variable.
like this:
$scope.populateLookup = function(lookup) {
$http({
url : <some URL>
dataType : "json",
method : "POST",
data : "action=3&lookup="+lookup,
headers : {"Content-Type" : "application/x-www-form-urlencoded; charset=utf-8"}
}).success(function(data) {
if ( angular.isArray(data.columns)) {
$scope.columns = data.columns;
} else {
$scope.columns = [data.columns];
}
}).error(function(error){
alert("There was an error");
});
};

Related

Unable to bind Json Data with Table Header using AngularJS

Im getting data in this format from api, but when i try binding it to table using angularjs it is creating empty space instead of values. Im also getting more then one table from some Api's please explain who to bind different datatables in different tables too. thanks
{"Table":
[{
"SchoolId":1,
"schoolname":"Microsoft",
"SCHOOLCODE":"29911583",
"WEBSITE":"JLR",
"USEREMAIL":"faucibus#aliquamiaculislacus.org",
"PHONE":"841-9331",
"ADDRESS1":"682-5760 Felis Street",
"ISACTIVE":0,
"PLANTYPE":3
}]
}
Angular Controller
SMSApp.factory('GetStudentService', function ($http) {
studobj = {};
studobj.getAll = function () {
var stud=[];
stud = $http({ method: 'Get', url: 'http://localhost:58545/api/Student?Studentid=1' }).
then(function (response) {
return response.data;
});
return stud;
};
return studobj;
});
SMSApp.controller('studentController', function ($scope, GetStudentService) {
$scope.msg = "Welcome from Controller";
GetStudentService.getAll().then(function (result) {
$scope.school = result;
console.log(result);
});
});
HTML Code
<tbody ng-controller="studentController">
<tr ng-repeat="schools in school track by $index">
<td>{{schools.SchoolId}}</td>
<td>{{schools.schoolname}}</td>
<td>{{schools.SCHOOLCODE}}</td>
<td>{{schools.WEBSITE}}</td>
<td>{{schools.USEREMAIL}}</td>
</tr>
</tbody>
WHAT I GET
Change in your Angular Controller :
SMSApp.controller('studentController', function ($scope, GetStudentService) {
$scope.msg = "Welcome from Controller";
GetStudentService.getAll().then(function (result) {
/********************* Changed Here ********************/
$scope.school = JSON.parse(result._body); // Or only JSON.parse(result)
$scope.school = $scope.school.table;
});
});
And your HTML Code :
<tbody ng-controller="studentController">
<tr ng-repeat="schools in school track by $index">
<td>{{schools.SchoolId}}</td>
<td>{{schools.schoolname}}</td>
<td>{{schools.SCHOOLCODE}}</td>
<td>{{schools.WEBSITE}}</td>
<td>{{schools.USEREMAIL}}</td>
</tr>
</tbody>
Naming the data school is confusing. Do instead:
GetStudentService.getAll().then(function (data) {
$scope.tableObj = data;
console.log(data);
});
<tbody ng-controller="studentController">
<tr ng-repeat="school in tableObj.Table track by school.SchoolId">
<td>{{school.SchoolId}}</td>
<td>{{school.schoolname}}</td>
<td>{{school.SCHOOLCODE}}</td>
<td>{{school.WEBSITE}}</td>
<td>{{school.USEREMAIL}}</td>
</tr>
</tbody>
From the Docs:
Best Practice: If you are working with objects that have a unique identifier property, you should track by this identifier instead of the object instance, e.g. item in items track by item.id. Should you reload your data later, ngRepeat will not have to rebuild the DOM elements for items it has already rendered, even if the JavaScript objects in the collection have been substituted for new ones. For large collections, this significantly improves rendering performance.
— AngularJS ng-repeat API Reference
Just replace your result with result.Table in your controller because if you properly see your response it is inside "Table" named array. Try this you should be able to see your records
SMSApp.controller('studentController', function ($scope, GetStudentService) {
$scope.msg = "Welcome from Controller";
GetStudentService.getAll().then(function (result) {
$scope.school = result.Table;
console.log(result);
});
});
Note: I have replaced your API call in the jsfiddle link with the response mentioned in the question.
JSFiddle Link : http://jsfiddle.net/zu8q7go6/9/

Angular ui router view loaded but not passing parameters

I'm working on a website with angular ui-router. There is a page which needs to pass some parameters to another view. I defined my states like this:
.state('locaties', {
url: "/locaties",
data: {rule: function($cookieStore) {} },
controller: "FranchisesCtrl",
templateUrl: "view/locaties.html"
})
.state('locaties.detail', {
params: {
locatieID: 1,
locatieName: "Derptown",
locatieLat: 50,
locatieLong: 50
},
url: "/:locatieName",
controller: "LocatieDetailCtrl",
templateUrl: "view/locatie.html",
resolve: {
locatiedetail:
function ($stateParams, $http){
var url ="http://website/api/franchises/" + $stateParams.locatieID + "/nl.json";
return $http.get(url).then(function(res){
return res.data;
});
}
}
})
Inside LocatieDetailCtrl there's this
angular.module('PremiumMeat').controller('FranchisesDetailCtrl',
function ($scope, $window, franchisedetail) {
$scope.franchiseDetail = franchisedetail;
});
The "Locaties" (plural) view works properly and when I click on a specific "locatie" (single), the url changes and the view gets loaded within the locaties view and no parameters are passed. On the image you can see the top 2 items from the "locaties" view. Then a single locatie is loaded under the "locaties" view. This should be a new page (view) with the parameters from the clicked locatie. Can anyone help me / explain, I'm rather new to angular, thank you.
Solution
The parameters where hard-coded, to make them dynamic, syntax needed adjustment according to angular docs.
params: {
locatieID: {value : "1"},
locatieName: {value : "Stad"},
locatieDescr: {value : "Beschrijving"},
locatieLat: {value: 51.2},
locatieLong: {value : 4.4}
},
Where parameters are passed with ui-href like this
<a ui-sref="locaties.detail({
locatieID: item.id,
locatieName: item.name,
locatieDescr: item.description,
locatieLat: item.location[0].lat,
locatieLong: item.location[0].long
})"
class="detail">Bekijk detail >></a>
The 'params' defined should return the key-value pair object.
But it is a better practice if you are passing values from one state to another to use 'data' instead of appending everything in the URL.
The following code should work :
//The following values are default values of the parameters
.state('locaties.detail', {
params: {
locatieID: '1',
locatieName: 'Derptown',
locatieLat: '50',
locatieLong: '50'
}, ........
This should work. The values expected are of string type and not number.
As far as your LocatieDetailCtrl is concerned, you need to inject what you have in the resolve of the 'locaties.detail' state (i.e. 'locatiedetail'). So your 'LocatieDetailCtrl' should look like following:
angular.module('PremiumMeat').controller('FranchisesDetailCtrl',
function ($scope, $window, franchisedetail, locatiedetail) {
$scope.franchiseDetail = franchisedetail; //make sure you have franchiseDetail as well.
$scope.locatiedetail = locatiedetail;
});
I hope that will work.

Firebase retrieve data shows only one result

I am trying to retrieve a data of objects and the result shows on the console but it only shows one result(the last result) on the page.
$http.get('/users').success(function(data) {
$scope.username = data; //assign data to username
console.log(data);
});
And in my Jade template, i have
section(data-ng-controller='browse')
h4 hi
ul(data-ng-repeat='user in username')
li {{user}}
I want to loop through this data
{
"google: xxxxxxxxxxxxx" : {
"name" : "ZZZ YYY",
"profile" : {
"briefProfile" : "Cost call",
"career" : "Web Developer",
"projects" : {
"-JjtSgiwkqFxTxMv0Gip" : "http://zipper.com"
}
},
"provider" : "google"
},
"google:xxxxxxxxxxx" : {
"name" : "SSS TTT",
"profile" : {
"briefProfile" : "Desired Intelligence",
"career" : "Consultant"
},
"provider" : "google"
}
}
Thanks.(i'm not using angularFire).
If you're using the $http service, then you're not using Firebase.
You are repeating the ul instead of the li. Also, {{user}} will be the whole user object, and you will see something like [Object object] on your page instead of a string. So call {{user.name}}.
ul
li(data-ng-repeat='user in users') {{user.name}}
Assuming that $http is there by mistake, and you meant to use Firebase instead, you probably want to start by reviewing the Firebase Getting Started guide
// Get a reference to users
var ref = new Firebase('https://<YOUR-FIREBASE>.firebaseio.com/users');
// Attach an asynchronous callback to read the data at users ref
ref.on("value", function(snapshot) {
console.log(snapshot.val());
$scope.users = snapshot.val();
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
});
If you're using AngularFire you should take a look at this:
Instead of using $http.get try:
var data = $firebaseArray(new Firebase("URL"));
$scope.data = data;
Don't forget to add $firebaseArray as a dependency in your controller.
More info on AngularFire docs:
https://www.firebase.com/docs/web/libraries/angular/api.html#angularfire-firebasearray
If you're not using AngularFire take a look at this:
var firebaseRef = new Firebase('YOUR-FIREBASE-URL/users/');
firebaseRef.on('value', function(dataSnapshot) {
var data = dataSnapshot.val();
console.log(data);
$scope.users = data;
// Might need to use $digest to update $scope.
$scope.$digest();
});
More about on() in Firebase docs:
https://www.firebase.com/docs/web/api/query/on.html

How to initialize array before $scope will be loaded in AngularJS application

I have problem with my AngularJS application. In my html view, i have list that contains JavaScript objects.
<div ng-init="initWeek()" ng-controller="TableController">
<div id="TaskImages"> <div ng-repeat="task in taskList"> <div id="TaskImg" ><br> {{task.title}}<br>{{task.start}} </div> </div></div>
I set taskList by using the Jquery/Ajax, which gets all task object from server.
function getTaskFromServer() {
$.ajax({
type : "POST",
url : "main_page",
success : function(data) {
var taskList = $.parseJSON(data);
week[0].push(taskList[0]);
},
});
My controller looks like this:
$scope.initWeek = function() {
getTaskFromServer();
};
$scope.taskList = week[currentlySelectedDay-1];
When I load application, the list "week" contains objects but in html view can see text.
I think that $scope.taskList is loaded before list "week".
For example, when I use:
$scope.initWeek = function() {
getTaskFromServer();
alert(week[0].lenght);
};
$scope.taskList = week[currentlySelectedDay-1];
Site displays alert and when i click Ok the text from taskList is a an website.
Since it is an asynchronous operation, you must set the taskList inside the ajax callback:
function getTaskFromServer() {
$.ajax({
type : "POST",
url : "main_page",
success : function(data) {
var taskList = $.parseJSON(data);
week[0].push(taskList[0]);
$scope.taskList = week[currentlySelectedDay-1];
},
});
}
It would be even better if you could replace the jquery ajax call with an angular call using $http.
Hope that helps.

Dynamic sort in backbone collection not working

So I have a very basic backbone collection and model. I currently do not have a view as I'm rendering the collection through a custom template. What I'd like to do is sort the collection through an event (clicking on a column header). The event sets a new comparator, and then fires the .sort() method on the collection. However, when I dump the collection data after the .sort(), the collect is in the same order. I'm new to backbone and collections, so perhaps I'm missing something. Here's my code:
var TicketCollection = Backbone.Collection.extend({
model : TicketModel,
initialize : function() {
},
fetch : function(options) {
options = options ? options : {};
var self = this;
$.ajax({
url : "/getTickets",
data : {},
method : "POST",
cache : false,
dataType : "json",
success : function(Json) {
self.reset(Json);
},
complete : options.complete
});
},
render : function() {
var self = this;
Base.renderTemplate({el : $("#ticketListContainer"), Template : "ticketList", data : {tickets : this.toJSON()}});
$("#ticketList").find("#tdHeadCompany").click(function() {
self.comparator = function(ticket) {
ticket.get("company");
};
self.sort();
console.log(JSON.stringify(self.toJSON()));
});
},
comparator : function(ticket) {
return ticket.get("number");
}
});
The console.log shows the collection is still in its original order, and not being ordered by "company" as I'd like when the company header is clicked. Any advice? Thanks!
And I was missing a return in my comparator function. Thanks for pointing that out, Andrew!

Resources