ui-router ui-view not updating info based on main view - angularjs

I have a main page displaying a list of houses and when I click on a particular house I want to display the house details. I am trying to achieve this using ui-view however, the house details are not showing.
These are my routes defined:
var app = angular.module('app', ['ui.router']);
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/about');
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'app/views/partial-home.html'
})
.state('about', {
url: '/about',
templateUrl: 'app/views/partial-about.html',
controller: 'inventoryCtrl'
})
.state('about.item', {
url: '/:id',
templateUrl: 'app/views/partial-about-item.html',
controller: 'detailsCtrl'
});
});
this is my main page html displaying a list of all houses:
<div ng-repeat="value in all | filter: (!!locationFilter || undefined) && {type: locationFilter} | filter: priceFilter | filter: datesFilter | orderBy:sortProp">
<ul>
<li><img src="app/images/{{value.image}}.jpg" alt="Smiley face" height="100" width="240"></li>
<li><strong>{{value.id}}</strong></li>
<li><strong>{{value.address}}</strong></li>
<li>city: {{value.city}}</li>
<li>postcode: {{value.postcode}}</li>
<li>price: £{{value.price}}</li>
<li>num_of_beds: {{value.num_of_beds}}</li>
<li>{{value.type}}</li>
<li>{{value.minutes}}</li>
<li>{{value.added}}</li>
</ul>
<a ng-href="#/about/{{value.address}}" class="btn btn-primary">View details</a>
</div>
<div ui-view></div>
this is my house details html displaying the house details which is only displaying the static text nothing inside ng-repeat or curly braces is shown
updated html:
<div>
<ul ng-repeat="item in singleHouse track by item.id">
<li>{{item.id}}</li>
<li>{{item.desc}}</li>
</ul>
</div>
this is my page details controller:
app.controller('detailsCtrl', ['$scope', 'DetailsFactory', '$stateParams', '$state', function($scope, DetailsFactory, $stateParams, $state) {
$scope.id = $stateParams.id;
DetailsFactory.getHouseDetails($stateParams.id).then(function(response){
$scope.singleHouse = response.detailsData.details;
console.log($scope.singleHouse);
})
}]);
I have added factory as well for the details house page:
app.factory('DetailsFactory', ['$http', '$stateParams', function($http, $stateParams) {
var urlBase = 'app/default/details.json';
var factory = {};
factory.getHouseDetails = function(id){
return $http.get(urlBase + id);
}
return factory;
}]);
and the json for the details page:
{
"detailsData":{
"details": [
{
"id": 1,
"desc": "Beautiful house blebel eble"
}, {
"id": 2,
"desc": "Beautiful house blebel eble"
}, {
"id": 3,
"desc": "Beautiful house blebel eble"
}, {
"id": 4,
"desc": "Beautiful house blebel eble"
}, {
"id": 5,
"desc": "Beautiful house blebel eble"
}, {
"id": 6,
"desc": "Beautiful house blebel eble"
}, {
"id": 7,
"desc": "Beautiful house blebel eble"
}, {
"id": 8,
"desc": "Beautiful house blebel eble"
}, {
"id": 9,
"desc": "Beautiful house blebel eble"
}, {
"id": 10,
"desc": "Beautiful house blebel eble"
}, {
"id": 11,
"desc": "Beautiful house blebel eble"
}, {
"id": 12,
"desc": "Beautiful house blebel eble"
}]
}
}

$stateParams.item just gives id. In your details controller you should get the house detail from server
app.controller('detailsCtrl', ['$scope', 'InventoryFactory', '$stateParams', '$state', function($scope, InventoryFactory, $stateParams, $state) {
InventoryFactory.getHouseDetail($stateParams.item).then(function(response){
$scope.singleHouse = response.data;
})
}]);
In your html
<ul ng-repeat="item in singleHouse">
<li>{{item.id}}</li>
<li>{{item.desc}}</li>
</ul>

Your ng-href="#/about/{{value.address}}" doesn't match up with your state declaration url: '/:item', it should be url: 'about/:item',

Related

Accessing data from a REST API in AngularJS

I have a REST api from elasticsearch. I want to retrieve the data of a specific field. That is, I want to retrieve the data in the Gender field. What I have done is I have consume the rest service in AngularJS as follows. But nothing is appearing on the browser. Can somebody help to achieve what I want to display?
angular.module("view.index", ['ngRoute'])
.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/menuIndex/', {
templateUrl: 'view-index/template/index.html',
controller: 'NewController',
controllerAs: 'newCtrl',
});
}])
.controller('NewController', ['$timeout', 'overlayMessage', '$location', 'userInformation', '$http', '$scope','menuService', function ($timeout, overlayMessage, $location, userInformation, $http, $scope, menuService) {
var myCtrl = this;
myCtrl.Form = {};
$http.get('http://admin:admin#localhost:9200/index1/_search?_source=Gender').
success(function(data) {
myCtrl.json = data;
});
}]);
The GET api http://admin:admin#localhost:9200/index-data/_search?_source=Gender returns me a json body like this:
{
"took": 17,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 30003,
"max_score": 1,
"hits": [
{
"_index": "index1",
"_type": "tbl",
"_id": "1",
"_score": 1,
"_source": {
"Gender": "Female"
}
},
{
"_index": "index1",
"_type": "tbl",
"_id": "2",
"_score": 1,
"_source": {
"Gender": "Male"
}
}
And in my front end, I want to access the data in the Gender field like this:
<div ng-controller="menuNsmCtrl">
<div ng-repeat="json in json">
<p>The ID is {{json.Gender}}</p>
</div>
</div>
First use then instead of success to catch the data. success is deprecated since the angular version 1.4
$http.get('http://admin:admin#localhost:9200/index1/_search?_source=Gender').
then(function(response) {
myCtrl.json = response.data;
});
}]);
now since you use controllerAs syntax you need to use the reference variable in the html also
<div ng-controller="NewController as myCtrl">
<div ng-repeat="json in myCtrl.json.hits.hits">
<p>The ID is {{json['_source'].Gender}}</p>
</div>
</div>

angular.forEach() not working

Hi friend I'm beginner in angular and getting stuck by using angular.forEach() function. I just want to call data from a nested array in data.json file. Please check my code below... ****I want to call data from --users-- key****
HTML
<div class="user-container" ng-controller="users">
<ul class="list">
<li ng-repeat="(key, value) in items">
{{key}} <p> {{value}}
</li>
</ul>
</div>
Problems with current code
When run my code in browser Its giving me only 2 <li> in ng-repeat then in {{Key}} I'm getting 0 in first <li> and 1 in second <li>
and in {{value}} I'm getting whole user list in first <li> and in second <li> their is no data
data.json
{
"data": {
"new": true,
"show_page": false,
"status": "signedin",
"users": [{
"Michele": {
"logo": "xyz.jpg",
"status": "active",
"active_since": 2015,
"order": 1
},
"Gerry": {
"logo": "xyz.jpg",
"status": "active",
"active_since": 2015,
"order": 1
}
}]
},
"success": true
}
Controller.js
var myApp = angular.module('app', []);
myApp.service('userData', ['$http', function($http){
return{
userslist : function(){
return $http({'url' : 'data.json', 'method' : 'GET'}).then(function(response){
return response.data;
}, function(data){
console.log(data)
})
}
}
}]);
myApp.controller('users', ['$scope', '$http', 'userData', function($scope, $http, userData){
userData.userslist().then(function(data){
//var provideDataKey = Object.keys(data.users)[0];
$scope.items = [];
angular.forEach(data, function(item){
//console.log(item.users);
$scope.items.push(item.users)
})
console.log($scope.items)
})
}]);
response is the HTTP response, with its body (data), headers, etc.
So response.data is the body, which looks like this:
{
"data": {
"new": true,
"show_page": false,
"status": "signedin",
"users": [{
"Michele": {
"logo": "xyz.jpg",
"status": "active",
"active_since": 2015,
"order": 1
},
"Gerry": {
"logo": "xyz.jpg",
"status": "active",
"active_since": 2015,
"order": 1
}
}]
},
"success": true
}
What you want is to access the users field of the data field of this body. So what you want is
userData.userslist().then(function(data){
$scope.items = data.data.users;
console.log($scope.items)
})
$scope. items is an array, not an object. You want to display the elements of this array. So the syntax is:
{{ user }}
Your JSON is awful, because each user is an object with a single field, and you have no way of knowing the name of that field. You'd better change it to
"users": [
{
"name": "Michele",
"logo": "xyz.jpg",
"status": "active",
"active_since": 2015,
"order": 1
},
{
"name": "Gerry",
"logo": "xyz.jpg",
"status": "active",
"active_since": 2015,
"order": 1
}
]
That way you could just do:
<li ng-repeat="user in items">
{{ user.name }}, active since {{ user.active_since }}.
use this
myApp.controller('users', ['$scope', '$http', 'userData', function($scope, $http, userData){
userData.userslist().then(function(data){
//var provideDataKey = Object.keys(data.users)[0];
$scope.items = [];
angular.forEach(data.users[0], function(item){
$scope.items.push(item);
})
console.log($scope.items)
})
}]);
you were iterating over data and not on users.

AngularJS: How to develop master with nested details using ng-repeat

i have read this post https://stackoverflow.com/a/18295177/6188148
but my json looks bit different. here is my json.
[{"ID":1,"Name":"Suzy","ParentID":0},
{"ID":2,"Name":"Somi","ParentID":1},
{"ID":3,"Name":"Romi","ParentID":2},
{"ID":4,"Name":"Jumi","ParentID":3},
{"ID":5,"Name":"Gargi","ParentID":0},
{"ID":6,"Name":"Sujoy","ParentID":5},
{"ID":7,"Name":"Kamal","ParentID":6},
{"ID":8,"Name":"Joy","ParentID":0},
{"ID":9,"Name":"Sumana","ParentID":8},
{"ID":10,"Name":"Alex","ParentID":0}]
in my case relation establish with ID and ParentID. the relation can be nested upto nth level. so tell me how to use ng-repeat to show parent and child data.
this way i tried
<div ng-app="myApp">
<ul class="nav nav-pills" data-ng-controller= "MasterDetails" >
<li
data-ng-repeat="parent in details | filter: { ParentID: 0 }" >
{{ parent.Name }}
<ul>
<li data-ng-repeat="child in details | filter: { ParentID: parent.ID }">
{{ child.Name }}
</li>
</ul>
</li>
</ul>
</div>
angular.module("myApp", []).
controller("MasterDetails", ['$scope', function($scope) {
$scope.details = [{"ID":1,"Name":"Suzy","ParentID":0},
{"ID":2,"Name":"Somi","ParentID":1},
{"ID":3,"Name":"Romi","ParentID":2},
{"ID":4,"Name":"Jumi","ParentID":3},
{"ID":5,"Name":"Gargi","ParentID":0},
{"ID":6,"Name":"Sujoy","ParentID":5},
{"ID":7,"Name":"Kamal","ParentID":6},
{"ID":8,"Name":"Joy","ParentID":0},
{"ID":9,"Name":"Sumana","ParentID":8},
{"ID":10,"Name":"Alex","ParentID":0}];
}]);
here is jsfiddle https://jsfiddle.net/tridip/s0svpaev/2/
the above code is working but not getting right output. hierarchy should be look like this way
Suzy
Somi
Romi
Jumi
Gargi
Sujoy
Kamal
Joy
Sumana
Alex
where i made the mistake in code for which i am not getting right output. thanks
Based on your link, I created this plnkr with some modifications to fit your needs.
I just added the getSubPeople function in the controller to get a sub array that represent the elder parents and pass them immediately to the directive for sub rendering:
Our partial:
<ul>
<li ng-repeat="p in peoples">
{{p}}
<div ng-switch on="p.ParentID > 0">
<div ng-switch-when="true">
<div ng-init="peoples = getSubPeople(p.ParentID);" ng-include="'partialPeoples.html'"></div>
</div>
</div>
</li>
</ul>
Our Controller :
var app = angular.module('angularjs-starter', []);
app.controller('MainCtrl', function($scope, $http) {
$scope.peoples = [{"ID":1,"Name":"Suzy","ParentID":0},
{"ID":2,"Name":"Somi","ParentID":1},
{"ID":3,"Name":"Romi","ParentID":2},
{"ID":4,"Name":"Jumi","ParentID":3},
{"ID":5,"Name":"Gargi","ParentID":0},
{"ID":6,"Name":"Sujoy","ParentID":5},
{"ID":7,"Name":"Kamal","ParentID":6},
{"ID":8,"Name":"Joy","ParentID":0},
{"ID":9,"Name":"Sumana","ParentID":8},
{"ID":10,"Name":"Alex","ParentID":0}];
$scope.getSubPeople = function(parentId) {
var arr = [];
for(var i=parentId; i>0 ; i--){
arr.push($scope.peoples[i-1]);
}
return arr;
}
});
Presume include jQuery and not care dom opt perfomance too much, This anwser can match your requirement.
angular.module('app', [])
.controller('appCtrl', function($scope) {
$scope.data = [{
"ID": 1,
"Name": "Suzy",
"ParentID": 0
}, {
"ID": 2,
"Name": "Somi",
"ParentID": 1
}, {
"ID": 3,
"Name": "Romi",
"ParentID": 2
}, {
"ID": 4,
"Name": "Jumi",
"ParentID": 3
}, {
"ID": 5,
"Name": "Gargi",
"ParentID": 0
}, {
"ID": 6,
"Name": "Sujoy",
"ParentID": 5
}, {
"ID": 7,
"Name": "Kamal",
"ParentID": 6
}, {
"ID": 8,
"Name": "Joy",
"ParentID": 0
}, {
"ID": 9,
"Name": "Sumana",
"ParentID": 8
}, {
"ID": 10,
"Name": "Alex",
"ParentID": 0
}];
})
.directive('tree',function($filter){
return {
restrict:'EA',
scope:{
data:'='
},
link:function(scope,element,attrs){
scope.data = $filter('orderBy')(scope.data,'ParentID');
var html = $('<ul id="tree-outer-0"></ul>');
element.append(html);
angular.forEach(scope.data,function(val,index){
var tree = $('<li id="tree-inner-'+val.ID+'">'+val.Name+'</li>');
var parent = $('ul#tree-outer-'+val.ParentID);
if(parent.length){
parent.append(tree);
}else{
var parents = $('li#tree-inner-'+val.ParentID);
var parent = $('<ul id="tree-outer-'+val.ParentID+'"></ul>');
parent.appendTo(parents).append(tree);
}
});
}
}
});
<script src="//cdn.bootcss.com/angular.js/1.5.5/angular.min.js"></script>
<script src="//cdn.bootcss.com/jquery/2.1.4/jquery.js"></script>
<div ng-app="app" ng-controller="appCtrl">
<tree data="data"></tree>
</div>

Get Json array that equals the value of $stateParam

I'm having trouble in fetching specific array in details page. $stateParams needs to be the same with the JSON array id but I can't print that on its template. I really appreciate any help. Thank you.
Services
angular.module('demo', ['ui.router']);
.factory('BookService', ['$http', function($http){
return {list: $http.get('data.json')}
}])
Routes
.config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/books');
$stateProvider
.state('books', {
url:'/books',
templateUrl: 'templates/books.html',
controller: 'BooksCtrl'
})
.state('books.detail', {
url: '/detail/:id',
templateUrl: 'templates/books-detail.html',
controller: 'BooksDetailCtrl'
});
}])
Controllers
.controller('BooksCtrl', ['$scope', 'BookService', function($scope, BookService){
BookService.list
.success(function(data){
$scope.books = data;
});
}])
.controller('BooksDetailCtrl', ['$scope', '$stateParams', 'BookService',
function($scope, $stateParams, BookService){
$scope.selectedBook = BookService.find(BookService.list, $stateParams.id);
}])
JSON File(data.json)
{ "demo_site": [{
"id": "1",
"title": "Demo 1",
"summary": "Summary 1",
"body": "test demo 1",
"image": "img/compress/placehold.jpg",
"source": "angular/source",
"demo_link": "http://github.com"
}, {
"id": "2",
"title": "Demo 2",
"summary": "Summary 2",
"body": "test demo 2",
"image": "img/compress/placehold.jpg",
"source": "angular/source",
"demo_link": "http://github.com"
}]
}
Templates
books.html
<ul>
<li ui-sref-action="selected" ng-repeat="book in books.demo_site">
<a ui-sref="books.detail({id: book.id})">{{ book.title }}</a>
</li>
</ul>
<div class="detail" ui-view></div>
books-detail.html
<div>
{{selectedBook.title}}
</div>
I've edited your code a bit and it works now. The most important change is mocking the BookService by bookServiceMock (I added it because I don't have access to your service).
app.js
var app = angular.module('demo', ['ui.router']);
app.config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/books');
$stateProvider
.state('books', {
url:'/books',
templateUrl: 'books.html',
controller: 'BooksCtrl'
})
.state('books.detail', {
url: '/detail/:id',
templateUrl: 'books-detail.html',
controller: 'BooksDetailCtrl'
});
}]);
app.service('bookServiceMock', function() {
var books =[{
"id": "1",
"title": "Demo 1",
"summary": "Summary 1",
"body": "test demo 1",
"image": "img/compress/placehold.jpg",
"source": "angular/source",
"demo_link": "http://github.com"
}, {
"id": "2",
"title": "Demo 2",
"summary": "Summary 2",
"body": "test demo 2",
"image": "img/compress/placehold.jpg",
"source": "angular/source",
"demo_link": "http://github.com"
}];
this.getBooks = function() {
return books;
};
this.getBook = function(id) {
for (var i = 0; i < books.length; i++) {
if (books[i].id === id) {
return books[i];
}
}
return null;
}
})
app.controller('BooksCtrl', ['$scope', 'bookServiceMock', function($scope, bookServiceMock){
console.log('BooksCtrl');
$scope.books = bookServiceMock.getBooks();
}]);
app.controller('BooksDetailCtrl', ['$scope', '$stateParams', 'bookServiceMock',
function($scope, $stateParams, bookServiceMock){
$scope.selectedBook = bookServiceMock.getBook($stateParams.id);
}]);
books.html
<ul>
<li ui-sref-action="selected" ng-repeat="book in books">
<a ui-sref="books.detail({id: book.id})">{{ book.title }}</a>
</li>
</ul>
<div class="detail" ui-view></div>
Here is the plunkr: http://plnkr.co/edit/VJxlqguJZGrIutAFLCNc

Bind scope property to tab title

I am new to angularJS and I am having trouble with binding properties of scope so two way binding can work properly. I am using sample code to generate tabs.
<div ng-app="SampleApp">
<div id="tabs" ng-controller="GridController as gridcon">
<ul>
<li ng-repeat="tab in tabs"
ng-class="{active:isActiveTab(tab.url)}"
ng-click="onClickTab(tab)">{{tab.title}}</li>
</ul>
<div id="mainView">
<div ng-include="currentTab"></div>
</div>
<input type="button" ng-click="changedata()" value="Check" />
</div>
</div>
Now my scope have two observable arrays and I want to show count of those arrays in tab title. I am using following code for controller.
var appRoot = angular.module('SampleApp', ["kendo.directives"]);
appRoot.controller('GridController', ['$scope', function ($scope) {
$scope.data1 = new kendo.data.ObservableArray([
{
issueId: 1,
issue: "County Incorrect"
},
{
issueId: 2,
issue: "City Incorrect"
},
{
issueId: 3,
issue: "Name Incorrect"
}
]);
$scope.data2 = new kendo.data.ObservableArray([
{
"id": 11,
"first_name": "James",
"last_name": "Butt",
"company_name": "Benton, John B Jr",
"address": "6649 N Blue Gum St",
"city": "New Orleans",
"county": "Bridgepoort",
"state": "LA",
"zip": 70116,
"phone1": "504-621-8927",
"phone2": "504-845-1427",
"email": "jbutt#gmail.com",
"web": "http://www.bentonjohnbjr.com"
},
{
"id": 12,
"first_name": "Josephine",
"last_name": "Darakjy",
"company_name": "Chanay, Jeffrey A Esq",
"address": "4 B Blue Ridge Blvd",
"city": "Brighton",
"county": "Livingston",
"state": "MI",
"zip": 48116,
"phone1": "810-292-9388",
"phone2": "810-374-9840",
"email": "josephine_darakjy#darakjy.org",
"web": "http://www.chanayjeffreyaesq.com"
}
]);
$scope.tabs = [{
title: 'Issue List (0)'.replace("0", $scope.data1.length),
url: 'tab1.html'
}, {
title: 'Corrected (0)'.replace("0", $scope.data2.length),
url: 'tab2.html'
}];
$scope.currentTab = 'tab1.html';
$scope.onClickTab = function (tab) {
$scope.currentTab = tab.url;
}
$scope.isActiveTab = function (tabUrl) {
return tabUrl == $scope.currentTab;
}
$scope.changedata = function () {
$scope.data1.pop();
$scope.data2.pop();
console.log($scope.data1.length);
console.log($scope.data2.length);
}
}]);
Now this works fine when you are loading page for first time. Now on a button click ("Check" button), I am modifying the arrays. What should I do so that tab title is always in sync with length of arrays ? I have tried observable objects but unless I am using binding in view, they will just notify the event. Is there no other way except handling change event of observable arrays ?
you can Copy this piece of code inside the $scope.changedata function.
$scope.tabs = [{
title: 'Issue List (0)'.replace("0", $scope.data1.length),
url: 'tab1.html'
}, {
title: 'Corrected (0)'.replace("0", $scope.data2.length),
url: 'tab2.html'
}];
Also it remains outside as well.

Resources