AngularJS $routeParams / service not fetching data from JSON - angularjs

On test-detail.html page (partial view), data from respective json files are not fetched/displayed, i.e. the controller TestDetailCtrl is called in test-detail.html (as can be seen on a working alert button), but params curly brackets in view (test-detail.html) are empty.
However ListController for test-list.html works and fetches the tests.json.
File structure:
index.html
(tests)
tests.json (content correctly displayed in test-list.html)
a.json
b.json
(js)
(partials)
(css)
partials/test-list.html:
<form action="" data-ng-repeat="test in tests | orderBy:orderProp">
<input type="checkbox" data-ng-model="item.selected" data-ng-change="change(item)">
<a href="#/tests/{{test.id}}">
<img data-ng-src="{{test.imageUrl}}" alt="{{test.name}}" class="test-thumb">
</a>
<a href="#/tests/{{test.id}}">
{{ test.name }}
</a><br />
</form>
partials/test-detail.html (where none of the data are displayed and all checkmarks are false):
<div class="main">
<img data-ng-src="{{mainImageUrl}}"/>
<h2>{{ test.name }}</h2>
<p>{{ test.description }}</p>
Customization:
<ul>
<li>Test items: {{test.customization.items | checkmark }}</li>
<li>Test duration: {{test.customization.duration | checkmark }}</li>
</ul>
</div>
route provider in js/app.js:
app.config(['$routeProvider',
{$routeProvider
.when('/tests',
{templateUrl: 'partials/test-list.html', controller: 'ListController'})
.when('/tests/:testId',
{templateUrl: 'partials/test-detail.html', controller: 'TestDetailCtrl'})
.otherwise({redirectTo: '/tests'});
}]);
RESTful handling with js/services.js:
var appServices;
appServices = angular.module('appServices', ['ngResource']);
appServices.factory('Test', ['$resource',
function($resource){
return $resource('tests/:testId.json', {}, {
query: {method:'GET', params:{testId:'tests'}, isArray:true}
});
}]);
controllers.js:
var ctr = angular.module('myApp.controller', []);
ctr.controller('ListController', ['$scope', 'Test', function ($scope, Test)
{$scope.tests = Test.query(); /*works*/
$scope.orderProp = 'duration';}]);
ctr.controller('TestDetailCtrl', ['$scope', '$routeParams', 'Test', function($scope, $routeParams, Test)
{$scope.$on('$routeChangeSuccess', function() {
$scope.test = Test.get({testId: $routeParams.testId}, function(test) {
$scope.mainImageUrl = test.screenshots[0];
});
$scope.setImage = function(imageUrl) {
$scope.mainImageUrl = imageUrl;
};
$scope.hello = function(name) {
alert('Test ' + (name || 'works' + '!')); /*works*/
}
})}
]);
Example test-a.json:
[{
id: "test-a",
name: "test a",
description: "text ... bla",
"customization": {
"items": true,
"duration": false}
}]

I think you are mixing aspx partials with angular-arrays here.
Angular ng-repeat will work on client side only and will evaluate your scope.tests array when it finishes loading.
Your aspx partial (test-detail.html) will probably work server-side and will depend on you data-binding it with a container.
Edit: Your test-a.json looks strange... why is it encapsulated with brackets? (Why is it an array?) The partials/test-a.html is not made for arrays. Try this JSON (test-a.json):
{
id: "test-a",
name: "test a",
description: "text ... bla",
"customization": {
"items": true,
"duration": false}
}

Related

AngularJS, updating scope between controllers and html

I have built a service that is keeping track of the id of a record within a telerik grid. On selecting a row in the grid the service successfully fires and updates the data. My problem is that the controller that handles my navigation doesn't see the change and I don't fully understand how to accomplish this as I am fairly new to angularjs and front end development.
app
.controller('FindCardCtrl', ['$scope', '$http', 'NavService', function($scope, $http, NavService) {
$http.get('../../sampleData/cardData.json').then(function(data) {
var cardObj = data.data.cards;
var grid = $("#grid").kendoGrid({
dataSource: {
data: cardObj.card,
},
columns: [{
hidden: true,
field: "id"
},
{
field: "card_number",
title: "Card Number"
},
{
field: "name_on_card",
title: "Name On Card"
},
{
field: "billing_zip_code",
title: "Billing Zip Code"
},
{
field: "balance",
title: "Balance"
}
],
noRecords: true,
editable: false,
sortable: true,
reorderable: true,
selectable: "row",
change: function(e) {
var selectedRows = this.select();
var selectedDataItems = [];
for (var i = 0; i < selectedRows.length; i++) {
var dataItem = this.dataItem(selectedRows[i]);
selectedDataItems.push(dataItem);
}
NavService.setCardId(selectedDataItems[0].id);
},
pageable: {
pageSize: 20,
previousNext: true,
input: true,
buttonCount: 5,
pageSizes: [20, 30, 40, "all"],
info: true,
messages: {
page: "Enter page"
}
},
filterable: {
mode: "menu",
ignoreCase: true,
operators: {
string: {
eq: "Equal to",
contains: "Contains",
startswith: "Begins with"
},
date: {
eq: "Equal to",
gt: "After",
lt: "Before",
eq: "Equals",
gte: "After or equal to",
lte: "Before or equal to"
}
}
}
});
});
}]);
'use strict';
app
.controller('NavCtrl', ['$scope', '$http', 'NavService', function($scope, $http, NavService) {
$scope.oneAtATime = false;
//$http.get('../../sampleData/cardData.json').then(function (data) {
//var card = getObjects(data, "id", NavService.cardData.cardId);
// });
$scope.$on('card-selected', function(event, NavService) {
console.log(NavService.cardData.cardId);
});
// console.log(NavService.cardData.cardId);
//$scope.cardId = NavService.cardData.cardId;
$scope.status = {
isFirstOpen: true
};
}]);
function getObjects(obj, key, val) {
var objects = [];
for (var i in obj) {
if (!obj.hasOwnProperty(i)) continue;
if (typeof obj[i] == 'object') {
objects = objects.concat(getObjects(obj[i], key, val));
} else if (i == key && obj[key] == val) {
objects.push(obj);
}
}
return objects;
}
'use strict';
/**
* #ngdoc overview
* #name backOfficeApp
* #description
* # backOfficeApp
*
* Main module of the application.
*/
/*jshint -W079 */
var app = angular
.module('backOfficeApp', [
'ngAnimate',
'ngCookies',
'ngResource',
'ngSanitize',
'ngTouch',
'ngMessages',
'picardy.fontawesome',
'ui.bootstrap',
'ui.router',
'ui.utils',
'angular-loading-bar',
'angular-momentjs',
'kendo.directives',
'FBAngular',
'lazyModel',
'angularBootstrapNavTree',
'angularFileUpload',
'oc.lazyLoad',
'ui.select',
'ui.tree',
'ui.calendar',
'pascalprecht.translate',
'ngMaterial',
'localytics.directives',
'ipsum',
'angular-intro',
'dragularModule'
])
.run(['$rootScope', '$state', '$stateParams', function($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$rootScope.$on('$stateChangeSuccess', function(event, toState) {
event.targetScope.$watch('$viewContentLoaded', function() {
angular.element('html, body, #content').animate({
scrollTop: 0
}, 200);
setTimeout(function() {
angular.element('#wrap').css('visibility', 'visible');
if (!angular.element('.dropdown').hasClass('open')) {
angular.element('.dropdown').find('>ul').slideUp();
}
}, 200);
});
$rootScope.containerClass = toState.containerClass;
});
}])
.config(['uiSelectConfig', function(uiSelectConfig) {
uiSelectConfig.theme = 'bootstrap';
}])
//angular-language
.config(['$translateProvider', function($translateProvider) {
$translateProvider.useStaticFilesLoader({
prefix: 'languages/',
suffix: '.json'
});
$translateProvider.useLocalStorage();
$translateProvider.preferredLanguage('en');
$translateProvider.useSanitizeValueStrategy(null);
}])
.config(['$provide', function($provide) {
$provide.factory('NavService', function($q) {
var dataHolder = {};
//It's important that you use an object or an array here a string or other
//primitive type can't be updated with angular.copy and changes to those
//primitives can't be watched.
dataHolder.cardData = {
"cardId": '0'
};
dataHolder.setCardId = function(id) {
var deferred = $q.defer();
var cardId = id;
angular.copy(cardId, dataHolder.cardData);
deferred.resolve(dataHolder.cardData);
return deferred.promise;
}
return dataHolder;
})
}])
<div id="sidebar-wrap" ng-controller="NavCtrl">
<uib-accordion close-others="oneAtTime" slimscroll="{height: '100%'}">
<div uib-accordion-group is-open="status.isFirstOpen" class="panel-default">
<ul id="navigation" nav-collapse ripple>
<li ui-sref-active="active">
<a ui-sref="client.dashboard">
<fa name="dashboard"></fa> <span>{{ 'Menu.DASHBOARD'| translate }}</span></a>
</li>
<li ui-sref-active="active" ng-class="{'open':$state.includes('client.order')}">
<a ui-sref="client.order">
<fa name="shopping-cart"></fa> <span>{{ 'Menu.ORDER_MANAGEMENT' | translate }}</span></a>
<ul>
<li ui-sref-active="active">
<a ui-sref="client.order_management.new">
<fa name="caret-right"></fa> {{ 'Menu.NEW_ORDER' | translate }}</a>
</li>
<li ui-sref-active="active">
<a ui-sref="client.order_management.history">
<fa name="caret-right"></fa> {{ 'Menu.HISTORY' | translate }}</a>
</li>
<li ui-sref-active="active">
<a ui-sref="client.order_management.cancel">
<fa name="caret-right"></fa> {{ 'Menu.CANCEL' | translate }}</a>
</li>
</ul>
</li>
<li ui-sref-active="active" ng-class="{'open':$state.includes('client.card')}">
<a ui-sref="client.card">
<fa name="credit-card"></fa> <span>{{ 'Menu.CARD_MANAGEMENT' | translate }}</span></a>
<ul>
<li ui-sref-active="active">
<a ui-sref="client.card_management.find">
<fa name="search"></fa> {{ 'Menu.FIND_CARD' | translate }}</a>
</li>
</ul>
<ul ng-if="cardId > 0">
<li ui-sref-active="active">
<a ui-sref="client.card_management.summary({cardId: cardId})">
<fa name="caret-right"></fa> {{ 'Menu.SUMMARY'| translate }} </a>
</li>
</ul>
</li>
</ul>
</div>
</uib-accordion>
</div>
You can use the event system in Angular to notify other controllers that they need to update their values:
app.service('MyService', function($rootScope) {
var MyService = this;
var item;
MyService.setItem = function(value) {
/*-- code to set item --*/
// notify other controllers
$rootScope.$broadcast('item-changed');
};
MyService.getItem = function() {
// api call to get item
// or get current item value from variable
};
});
app.controller('MyOtherController', function($scope, MyService) {
$scope.$on('item-changed', function() {
MyService.getItem().then(function(result) {
$scope.item = result;
});
});
});
In your NavCtrl, you are most of the way there, you just need to set the scope variable to the new cardId in your event listener:
.controller('NavCtrl', [
'$scope', '$http', 'NavService',
function($scope, $http, NavService) {
//...
$scope.$on('card-selected', function(event, NavService) {
console.log(NavService.cardData.cardId);
$scope.cardId = NavService.cardData.cardId;
});
//...
}]);
You can't inject $scope into a service, but you can inject $rootScope. Broadcasting an event on $rootScope with send it to all scopes. Any scope that is listening for it will be able to respond to it.

Restangular / Json-ld | I can get the data, but I can't show them

I'm new in Angular and need your help.
With my team, we made a PHP REST API in Symfony that we want to connect to an Angular client.
I already have the Angular app..
I can see in my XHR requests that i actually get the entities and their properties (users).
But in my view, i tried some {{ user.name }} with ng-repeat but it dosen't show anything.
Datas are sent in Json-ld and we use Restangular to read them.
Here some code :
app.js :
angular
.module('frontApp', [
'ngAnimate',
'ngCookies',
'ngResource',
'ngRoute',
'ngSanitize',
'ngTouch',
'restangular'
])
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.when('/about', {
templateUrl: 'views/about.html',
controller: 'AboutCtrl'
})
.otherwise({
redirectTo: '/'
});
})
.config(['RestangularProvider', function (RestangularProvider) {
// The URL of the API endpoint
RestangularProvider.setBaseUrl('http://localhost:8000');
// JSON-LD #id support
RestangularProvider.setRestangularFields({
id: '#id'
});
RestangularProvider.setSelfLinkAbsoluteUrl(false);
RestangularProvider.setResponseExtractor(function(response) {
var newResponse = response;
if (angular.isArray(response)) {
angular.forEach(newResponse, function(value, key) {
newResponse[key].originalElement = angular.copy(value);
});
} else {
newResponse.originalElement = angular.copy(response);
}
return newResponse;
});
// Hydra collections support
RestangularProvider.addResponseInterceptor(function (data, operation) {
// Remove trailing slash to make Restangular working
function populateHref(data) {
if (data['#id']) {
data.href = data['#id'].substring(1);
}
}
// Populate href property for the collection
populateHref(data);
if ('getList' === operation) {
var collectionResponse = data['hydra:member'];
collectionResponse.metadata = {};
// Put metadata in a property of the collection
angular.forEach(data, function (value, key) {
if ('hydra:member' !== key) {
collectionResponse.metadata[key] = value;
}
});
// Populate href property for all elements of the collection
angular.forEach(collectionResponse, function (value) {
populateHref(value);
});
return collectionResponse;
}
return data;
});
}])
;
main.js :
angular.module('frontApp')
.controller('MainCtrl', function ($scope, Restangular) {
$scope.ami1 = Restangular.one('amis',1).get();
$scope.test ='Test';
var amis = Restangular.all('amis');
amis.getList().then(function (ami) {
$scope.ami = ami;
});
});
main.html:
<div class="jumbotron">
<p>Liste d'amis :</p>
{{ ami1.nom }}
{{ test }}
<div ng-repeat="ami in amis" id="{{ ami['#id'] }}" class="row marketing">
<h1>{{ ami.nom }}</h1>
<h2>{{ ami.prenom }}</h2>
<h3>{{ ami.id }}</h3>
</div>
chrome console
Thanks for helping!
I found by myself, here is the code :
<div ng-repeat="ami in amis" id="{{ ami['#id'] }}" class="row marketing">
<h1>Nom: {{ ami.nom }}</h1>
<h2>Prenom: {{ ami.prenom }}</h2>
<h3>Date de naissance: {{ ami.dateNaissance }}</h3>
<h4>Telephone(s): </h4>
<div ng-repeat="telephone in ami.telephones" id="{{ telephone['#id'] }}">
{{ telephones[$index].numero }}
</div>
</div>
in your controller ...
$scope.amis = Restangular.all('amis').getList();
if that doesn't work ...
Restangular.all('amis').getList().then(function(response) {
$scope.amis=response;
}).catch(function(error) {
console.log(error);
})
Ok now i have another issue.
I have all of my 'ami' and their properties so it's really great, but my 'ami' have many 'telephone' ids in it.
What i try to do is to have my 'ami' 'numero' from 'telephone' with this telephone id.
i can list all of my 'amis' with telephon id in it, and all of my 'telephones' with the numeros in it.
Thanks angain :)

"Conroller as" with ng-repeat with array of objects (does not work with 'this')

I noticed that for me this shows nothing in ng-repeat:
<ul ng-controller="UserCtrl as ctrl">
<li ng-repeat="user in ctrl.users">
{{user.name}}
</li>
</ul>
But this, works ok:
<ul ng-controller="UserCtrl">
<li ng-repeat="user in users">
{{user.name}}
</li>
</ul>
Why is that?
My Controller code is simple as that:
angular.module('main.controllers').controller('UserCtrl', ['$scope', 'UserResource', function UserCtrl($scope, UserResource) {
$scope.users = UserResource.list(); // works with $resource service
// ideally I would like type "var users = ..." without using $scope
var ctrl = this;
this.users = function() {
return UserResource.list();
};
return this;
}
where users are json array of objects I'm eventually getting as resolved promise result:
[
{ id: "1", name: "name1" },
{ id: "2", name: "name2" },
{ id: "3", name: "name3" }
]
Update:
The whole point is that it does not work with this.users and controller-as notation when it is wrapped in promise that I'm getting from $resource service.
return $resource(' /rest/user-api/user/:id/:action',
{id: "#id"}, //parameters default
{
list: { method: "GET", params: {action : "list"}, isArray: true},
});
In you controller you've got
this.users = function() ..
so in you view you need to execute that function to get users
<li ng-repeat="user in ctrl.users()">
this.users should be rather array like in my demo this.users2 and in that case you can use it in repeater as
<li ng-repeat="user in ctrl.users2">
var app = angular.module('app', []);
angular.module('app').service("userService", function($timeout, $q) {
this.getData = function() {
var deffered = $q.defer();
$timeout(function() {
var arr = [{
id: 1,
name: "Jack from Service"
}];
deffered.resolve(arr);
}, 2000);
return deffered.promise;
};
return this;
});
angular.module('app').controller('UserCtrl', ['userService',
function UserCtrl(userService) {
// ideally I would like type "var users = ..." without using $scope
var ctrl = this;
ctrl.users = function() {
return [{
id: 1,
name: "Jack Function"
}];
};
ctrl.users2 = [{
id: 1,
name: "Jack Array"
}];
////// users from service
this.usersFromService = [];
function activate() {
userService.getData().then(function(data) {
angular.copy(data, ctrl.usersFromService);
});
}
activate();
return this;
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="app">
<ul ng-controller="UserCtrl as ctrl">
<li ng-repeat="user in ctrl.users2">
{{user.name}}
</li>
<li ng-repeat="user in ctrl.usersFromService">
{{user.name}}
</li>
</ul>
</body>
My answer is that:
When I do this:
<ul ng-controller="UserCtrl as ctrl">
<li ng-repeat="user in ctr.users">
It does not work.
When I do this:
<ul ng-controller="UserCtrl as userCtrl">
<li ng-repeat="user in userCtrl.users">
or UserCtrl as a or UserCtrl as b ... - it works.
I just does not like ctrl as a name.
Thanks to all who were not voting "close". I can NOT explain how it differs from that I got as replies. In my case I use end-to end angular - NodeJS application that actually does whole client-server communication. Not sure it matters.
Maybe it clashes with another scopes.. I'm not sure yet. But the general advice - try to change the name after "as" and see what happen If you have issue like that. I know it's weird.

How should you access controller functions from other modules

I am having a hard time understanding how Modules should interact with each other in Angularjs. I would like to break the application into nice small modules, but I cannot seem to find the correct way to have these modules interact with each other.
JSFiddle:
http://jsfiddle.net/jwest80/o5o3sr8q/4/
The code shows a breadcrumb I would like to have at the top of the page. The BreadCrumb is in its own module 'bread' and included inside a parent module 'ngFSCH'.
There is a list outside BreadCrumb controller section whose actions should add breadcrumbs. However, I do not understand the correct way to access this addCrumb function. I can only make it work if it is called from inside the breadcrumb controller section in the markup.
Markup:
<div ng-app="ngFSCH">
<section ng-controller="BreadCrumbsCtrl">
<span ng-repeat="crumb in crumbs" class="breadcrumbs">
<span ng-hide="isLast($index)" ng-click="selectCrumb($index)">{{crumb.text}} > </span>
<span ng-show="isLast($index)">{{crumb.text}}</span>
</span>
</section>
<section>
<h4>Add Some Crumbs</h4>
<ul>
<li>Company</li>
<li>Department</li>
<li>User</li>
</ul>
</section>
</div>
Script:
var ngFSCH = angular.module('ngFSCH', ['bread']);
(function () {
var app = angular.module('bread', []);
app.controller('BreadCrumbsCtrl', ['$scope', '$log', function ($scope, $log) {
$scope.crumbs = [{ text: "Crumb 1", url: "url1" }, { text: "Crumb 2", url: "url2" }];
$scope.isLast = function(index) {
return index === $scope.crumbs.length-1;
}
$scope.addCrumb = function (newCrumb) {
$scope.crumbs.push({ text: newCrumb, url: "TestURL" });
}
$scope.selectCrumb = function (index) {
$log.info($scope.crumbs[index].url);
$scope.crumbs = $scope.crumbs.slice(0, index + 1);
}
}]);
})();
I would encapsulate the bread crumb functionality in a service and create a controller for the section with the links (that add the breadcrumbs). The new controller can then use the service to add and remove crumbs from the array. You can also add the crumbs array into a value.. Your controllers can then expose the add and select features to the tiny portions of html they control without polluting other sections of your page.
Here is the result. Hope it helps!
JSFiddle
Here is the code:
var app = angular.module('bread', []);
app.value('crumbs', [
{ text: "Crumb 1", url: "url1" },
{ text: "Crumb 2", url: "url2" }
]);
app.factory("BreadCrumbsService", ['$log', 'crumbs', function ($log, crumbs) {
var service = {
getCrumbs: getCrumbs,
addCrumb: addCrumb,
selectCrumb: selectCrumb
};
return service;
//I did not add a set crumbs because you can set it directly.
function getCrumbs(){
return crumbs;
}
function addCrumb(newCrumb) {
crumbs.push({
text: newCrumb,
url: "TestURL"
});
}
function selectCrumb(index) {
$log.info(crumbs[index].url);
crumbs = crumbs.slice(0, index + 1);
}
}]);
app.controller('BreadCrumbsCtrl', ['$scope', 'BreadCrumbsService', function ($scope, BreadCrumbsService){
$scope.crumbs = BreadCrumbsService.getCrumbs;
$scope.selectCrumb = BreadCrumbsService.selectCrumb;
$scope.isLast = function (index) {
return index === BreadCrumbsService.getCrumbs().length - 1;
}
}]);
app.controller('AddLinksCtrl', ['$scope', 'BreadCrumbsService', function ($scope, BreadCrumbsService) {
$scope.addCrumb = BreadCrumbsService.addCrumb;
}]);
Here is the links section with the new controller:
<section ng-controller="AddLinksCtrl">
<h4>Add Some Crumbs</h4>
<ul>
<li>Company</li>
<li>Department</li>
<li>User</li>
</ul>
</section>
That is intended because you are working within the scope of the controller. How about moving the ng-controller directive to the containing div where ng-app is?
<div ng-app="ngFSCH" ng-controller="BreadCrumbsCtrl">

How to display JSON list data in angularjs

I am new to Angularjs and having trouble displaying data . i.e. Json array
This is the result of my rest service call:
{
"users": [{
"id": 1,
"firstname": "Naveen",
"lastname": "Dutt",
"email": "navee23ndutt12.vyas#gmail.com",
"telephone": "7829418456445355"
}]
}
And this is my controller:
app.controller('MyCtrl2', ['$scope', 'NFactory', function ($scope, NFactory) {
alert("here??");
$scope.bla = NFactory.query;
alert("here??" + $scope.bla);
NFactory.get({}, function (nFactory) {
$scope.allposts = nFactory.firstname;
})
}]);
This is my html:
<div>
<ul >
<li ng-repeat="user in bla"> {{ user.firstname }} </li>
</ul>
</div>
but it doesnt show anything on UI. what can be the problem? please suggest.
It happens because you call async task. I would wrap result with promise.
Here is basic simulation of async call:
Demo Fiddle
var app = angular.module('myModule', ['ngResource']);
app.controller('fessCntrl', function ($scope, Data) {
Data.query()
.then(function (result) {
console.log(result);
$scope.bla = result.users;
}, function (result) {
alert("Error: No data returned");
});
});
app.$inject = ['$scope', 'Data'];
app.factory('Data', ['$resource', '$q', function ($resource, $q) {
var data = {
"users": [{
"id": 1,
"firstname": "Naveen",
"lastname": "Dutt",
"email": "navee23ndutt12.vyas#gmail.com",
"telephone": "7829418456445355"
}]
};
//Actually we can use $resource
//var data = $resource('localhost/shfofx/PHP/Rest/alertLossDetails.php',
// {},
// { query: {method:'GET', params:{}}}
// );
var factory = {
query: function (selectedSubject) {
var deferred = $q.defer();
deferred.resolve(data);
return deferred.promise;
}
}
return factory;
}]);
If $scope.bla in your case is
{"users":[{"id":1,"firstname":"Naveen","lastname":"Dutt","email":"navee23ndutt12.vyas#gmail.com","telephone":"7829418456445355"}]
then your template should look like this:
<ul >
<li ng-repeat="user in bla.users"> {{ user.firstname }} </li>
</ul>
Another way would be to change the code inside your Controller like this:
$scope.bla = NFactory.query.users;
and leave template as you have it.
If NFactory.query is string you need to parse it as JSON first.
$scope.bla=JSON.parse(NFactory.query);
and then
<ul >
<li ng-repeat="user in bla.users"> {{ user.firstname }} </li>
</ul>
Hope this will help...
Shouldn't it be a method call: NFactory.query() ?
Please show the NFactory source.
UPDATE: Try responding just array from server:
[{
"id": 1,
"firstname": "Naveen",
"lastname": "Dutt",
"email": "navee23ndutt12.vyas#gmail.com",
"telephone": "7829418456445355"
}]
and use NFactory.query()

Resources