nested states using Angular ui-router - angularjs

I am learning Angular and trying to design a website that has nested states. First of all I am not sure if my solution is right! the data structure is like the sample below. I am trying to display everything in one page which I call it "showcase". On showcase (state:"showcase"), you will see a list of all the categories and if you click on for example category1 all the subcategories in category1 will be displayed in the same page but different state (state:showcase.category1). This goes the same for each subcategories as well so if you click on e.g. subcategory2 it's supposed to display all the products in the subcategory2 and change the state to showcase/category1/subcategory2. I am trying to build this all static as well so there will be no server side.
I have created a little Plunker you can check out here -- > http://plnkr.co/edit/AkuCJXev6NzmgbqBMUrn
Is this a good solution for what I'm trying to accomplish, and if not how should I redirect my approach.
If this is the right approach how can I manipulate DOM in different states dynamically (e.g. ui-sref for links)
Thanks!
[
{
"title" : "category1",
"url" : "category1",
"imgUrl" : "http://lorempixel.com/200/200",
"subCats" : [
{
"title" : "subCat1",
"url" : "subCat1",
"imgUrl" : "http://lorempixel.com/200/200",
"products" : [
{
"title" : "product1",
"imgUrl" : "http://lorempixel.com/200/200"
},
{
"title" : "product2",
"imgUrl" : "http://lorempixel.com/200/200"
}
]
},
{
"title" : "subCat2",
"url" : "subCat2",
"imgUrl" : "http://lorempixel.com/200/200",
"products" : [
{
"title" : "product3",
"imgUrl" : "http://lorempixel.com/200/200"
},
{
"title" : "product4",
"imgUrl" : "http://lorempixel.com/200/200"
}
]
}
]
},
{
"title" : "category2",
"url" : "category2",
"imgUrl" : "http://lorempixel.com/200/200",
"subCats" : [
{
"title" : "subCat3",
"url" : "subCat3",
"imgUrl" : "http://lorempixel.com/200/200",
"products" : [
{
"title" : "product5",
"imgUrl" : "http://lorempixel.com/200/200"
},
{
"title" : "product6",
"imgUrl" : "http://lorempixel.com/200/200"
}
]
},
{
"title" : "subCat4",
"url" : "subCat4",
"imgUrl" : "http://lorempixel.com/200/200",
"products" : [
{
"title" : "product7",
"imgUrl" : "http://lorempixel.com/200/200"
},
{
"title" : "product8",
"imgUrl" : "http://lorempixel.com/200/200"
}
]
}
]
}
]

What your definition is missing is the view nesting - and that means $scope inheritance. I updated your plunker and make it working.
I changed your templaes, to also provide target for your child state (see the <ul> is now wrapped with ui-view - target for child)
<h1>Showcase</h1>
<div ui-view="">
<ul>
<li class="text-center thumbnail list-inline" ng-repeat=" category in categories">
<img src="{{category.imgUrl}}" alt="" />
<a ui-sref="showcase.category({category: category.url})">{{category.title}}</a>
</li>
</ul>
</div>
That will replace this content with a child content. And also we will have the $scope inherited (read more here about sharing data among states)
Here is updated state def:
.state('showcase', {
url: "/",
templateUrl: "pages/showcase.html"
})
.state('showcase.category', {
url: "^/:category",
templateUrl: "pages/subcategory.html",
controller: 'categoryCtrl',
})
.state('showcase.category.subcategory', {
url: "/:subcategory",
templateUrl: "pages/product.html",
controller: 'productCtrl',
});
And new controllers:
.controller('categoryCtrl', ['$scope', '$stateParams',
function($scope, $stateParams) {
$scope.category = $stateParams.category;
$scope.subCats = _.find($scope.categories, { "url": $stateParams.category }).subCats;
}
])
.controller('productCtrl', ['$scope', '$stateParams',
function($scope, $stateParams) {
$scope.subcategory = $stateParams.subcategory;
$scope.products = _.find($scope.subCats, { "url": $stateParams.subcategory}).products;
}
])
Check the updated plunker here
Also check these:
How do I share $scope data between states in angularjs ui-router?
multiple ui-view html files in ui-router

Related

I want to print long_name from the json data using angularjs

I am trying to fetch the long_name from the below JSON data using angular js but unable to fetch.
CODE:
{
"results" : [
{
"address_components" : [
{
"long_name" : "700109",
"short_name" : "700109",
"types" : [ "postal_code" ]
},
{
"long_name" : "Kolkata",
"short_name" : "Kolkata",
"types" : [ "locality", "political" ]
},
{
"long_name" : "West Bengal",
"short_name" : "WB",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "India",
"short_name" : "IN",
"types" : [ "country", "political" ]
}
],
"formatted_address" : "Kolkata, West Bengal 700109, India",
"geometry" : {
"bounds" : {
"northeast" : {
"lat" : 22.6902065,
"lng" : 88.38850289999999
},
"southwest" : {
"lat" : 22.6715168,
"lng" : 88.35748319999999
}
},
"location" : {
"lat" : 22.6808046,
"lng" : 88.37577829999999
},
"location_type" : "APPROXIMATE",
"viewport" : {
"northeast" : {
"lat" : 22.6902065,
"lng" : 88.38850289999999
},
"southwest" : {
"lat" : 22.6715168,
"lng" : 88.35748319999999
}
}
},
"place_id" : "ChIJ1-N4xFyc-DkRzfGq4MWZa1g",
"types" : [ "postal_code" ]
}
],
"status" : "OK"
}
I am using the following code to solve this problem but it does not show anything
CODE:
<div ng-app="myApp" ng-controller="myController">
<ul>
<li ng-repeat="record in records">
{{record.long_name}}
</li>
</ul>
</div>
<script>
var app=angular.module("myApp",[]);
app.controller("myController",function($scope,$http){
$http.get("https://maps.googleapis.com/maps/api/geocode/json?address=700109&key=AIzaSyDNK47S-6brePCvm1Hr6L7RFWAZvsngj1E")
// $http.get("https://www.styfash.com/post/data.json")
.then(function(result){
$scope.records=result.data.results.address_components;
});
});
</script>
Whenever I am trying to using $scope.records=result.data.results and printing {{record.address_components}} it is working properly but whenever I am trying to use the above-mentioned code it is not showing anything on the screen.
I am new to angular js.
Try
$scope.records=result.data.results[0].address_components;
What you should understand is, result.data.results is an array. Therefore you should traverse through that to obtain the child records. Check the code sample below.
var app = angular.module('myApp', []);
app.controller('myController', function ($scope, $http) {
$http.get("https://maps.googleapis.com/maps/api/geocode/json?address=700109&key=AIzaSyDNK47S-6brePCvm1Hr6L7RFWAZvsngj1E")
.then(function(result){
$scope.records=result.data.results;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myController">
<ul>
<div ng-repeat="record in records">
<li ng-repeat="address in record.address_components">
{{address.long_name}}
</li>
</div>
</ul>
</div>
if you just need the first record, change this line in your code
$scope.records=result.data.results.address_components;
to this
$scope.records=result.data.results[0].address_components;

ng-repeat value array angularjs

Sorry for the title, this is my first post.
OK, my problem is, I have this JSON:
{
"nodes" : [
{
"node" : {
"Title" : "this is a title",
"slideshowImage" : [
{
"src" : "imagen.png",
"alt" : ""
},
{
"src" : "imagen.png",
"alt" : ""
},
{
"src" : "imagen.png",
"alt" : ""
},
{
"src" : "imagen.png",
"alt" : ""
}
],
"Thumbnail" : {
"src" : "imagen.png",
"alt" : ""
},
"id" : "28"
}
}
]
}
How can I get a ng-repeat to slideshowImage
Ex: ng-repeat="node in items.slideshowImage"
{{node.node.slideshowImage.src}}
Am I doing it wrong?
Make sure your object is assigned to nodes object, then it would be simple like below.
ng-repeat="image in nodes.node.slideshowImage"
If you wanna ng-repeat in view Directly Like following :-
<div ng-repeat="N1 in sampleData.nodes">
<div ng-repeat="N2 in N1.node.slideshowImage">
{{N2.src}}
</div>
</div> <!-- Looped down to Subnodes For your Understanding --!>
Or Just Save it in to a scope Quick way :-
$scope.quickData=$scope.sampleData.nodes[0].node.slideshowImage; // as per data length
Now Roll it (ng-repeat) :-
<div ng-repeat="quick in quickData">
{{quick.src}}
</div>
https://plnkr.co/edit/EhuLmjzNa5srX2AV2gqT?p=preview
Both results are saved in Plunker
Happy Learning !!
You should do
ng-repeat="item in nodes.node.slideshowImage"
and in your views
{{ item.src }}

how to get selected node value for treeview using click event in angularjs directives

i am using directive concept in angularjs to display selected node value for tree view using click event function in angularjs.below is my sample code
Tree.html:
<div
data-angular-treeview="true"
data-tree-model="roleList"
data-node-id="roleId"
data-node-label="roleName"
data-node-children="children"
data-ng-click="selectNode(roleList[1])"
data-node-children="children">
</div>
treeviewcontroller.js:
$scope.roleList1 = [
{ "roleName" : "User", "roleId" : "role1", "children" : [
{ "roleName" : "subUser1", "roleId" : "role11", "children" : [] },
{ "roleName" : "subUser2", "roleId" : "role12", "children" : [
{ "roleName" : "subUser2-1", "roleId" : "role121", "children" : [
{ "roleName" : "subUser2-1-1", "roleId" : "role1211", "children" : [] },
{ "roleName" : "subUser2-1-2", "roleId" : "role1212", "children" : [] }
]}
]}
]},
{ "roleName" : "Admin", "roleId" : "role2", "children" : [] },
{ "roleName" : "Guest", "roleId" : "role3", "children" : [] }
];
Treeview.js:
scope.selectNode = function(val)
{
alert(val.roleName);
}
output:
user
subuser1
subuser1-1
Admin
subadmin1
from this output in alert place 'Admin' will be dispalyed by click on Admin node.but i want to display dynamically selected node value in click event function.please suggest me how to do this.
Thanks
In order to dynamically select node of the tree I did following:
Let's say you want to select first (top, [0]) element of your tree.
so first add data-tree-id="myTreeId" to your HTML:
<div
data-angular-treeview="true"
data-tree-model="roleList"
data-node-id="roleId"
data-node-label="roleName"
data-node-children="children"
data-ng-click="selectNode(roleList[1])"
data-node-children="children"
data-tree-id="myTreeId">
</div>
than in Controller:
$scope.roleList1[0].selected = "selected";
$scope.myTreeId.currentNode = $scope.roleList1[0];
In Tree.html :
Add line :
data-tree-id="mytree"
Modify data-ng-click event :
data-ng-click="selectNode(mytree.currentNode.roleName)"
In Treeview.js :
scope.selectNode = function(val) { alert(val); }

Angular JS - Loading modules from different files

I'm using a few modules from http://mgcrea.github.io/angular-strap/ and a tree view: http://ngmodules.org/modules/angular.treeview and I'm having problems when loading them. For example, I've splitted treeview.js in 2 files: 1 containing the controller and another containing the directive (as I saw on some posts that it's a good practice for Angular):
app.js -> loading flexylaout, modal and a grid
var app = angular.module('app',['flexyLayout','ui.bootstrap','ngGrid']);
treeController.js
(function(){
app.controller('TreeCtrl', function($scope){
$scope.roleList1 = [
{ "roleName" : "Escapamentos e Catalisadores", "roleId" : "role1", "children" : [
{ "roleName" : "Silencioso Intermediario", "roleId" : "role12", "children" : [
{ "roleName" : "Composicao", "roleId" : "role121", "children" : [
{ "roleName" : "Material 1", "roleId" : "role1211", "children" : [] },
{ "roleName" : "Material 2", "roleId" : "role1212", "children" : [] }
]}
]}
]},
{ "roleName" : "Arquivo 1", "roleId" : "role2", "children" : [] },
{ "roleName" : "Arquivo 2", "roleId" : "role3", "children" : [] }
];
//test tree model 2
$scope.roleList2 = [
{ "roleName" : "Tubos", "roleId" : "role1", "children" : [
{ "roleName" : "Galvanizados", "roleId" : "role11", "collapsed" : true, "children" : [] },
{ "roleName" : "Conducao", "roleId" : "role12", "collapsed" : true, "children" : [
{ "roleName" : "Material 1", "roleId" : "role121", "children" : [
{ "roleName" : "Material 2", "roleId" : "role1211", "children" : [] },
{ "roleName" : "Material 3", "roleId" : "role1212", "children" : [] }
]}
]}
]}
];
});
})();
directive.js
(function(){
app.directive('treeModel',function($compile){
return{
restrict:"A",
link:function(a,g,c){
var e=c.treeModel,
h=c.nodeLabel||"label",
d=c.nodeChildren||"children",
k='<ul><li data-ng-repeat="node in '
+e+'"><i class="collapsed" data-ng-show="node.'
+d+'.length && node.collapsed" data-ng-click="selectNodeHead(node, $event)"></i><i class="expanded" data-ng-show="node.'
+d+'.length && !node.collapsed" data-ng-click="selectNodeHead(node, $event)"></i><i class="normal" data-ng-hide="node.'
+d+'.length"></i> <span data-ng-class="node.selected" data-ng-click="selectNodeLabel(node, $event)">{{node.'
+h+'}}</span><div data-ng-hide="node.collapsed" data-tree-model="node.'
+d+'" data-node-id='
+(c.nodeId||"id")+" data-node-label="
+h+" data-node-children="
+d+"></div></li></ul>";
e&&e.length&&(c.app?(a.$watch(e,function(m,b){
g.empty().html($compile(k)(a))
},
!1),
a.selectNodeHead=a.selectNodeHead||function(a,b){
b.stopPropagation&&b.stopPropagation();
b.preventDefault&&b.preventDefault();
b.cancelBubble=!0;
b.returnValue=!1;
a.collapsed=!a.collapsed
},
a.selectNodeLabel=a.selectNodeLabel||function(c,b){
b.stopPropagation&&b.stopPropagation();
b.preventDefault&&b.preventDefault();
b.cancelBubble=!0;
b.returnValue=!1;
a.currentNode&&a.currentNode.selected&&(a.currentNode.selected=void 0);
c.selected="selected";
a.currentNode=c
}):g.html($compile(k)(a)))
}
}
});
})();
What I'm willing to do is: when the page loads, a tree with that data should appear but it doesn't. Before I splitted treeview.js, the code was:
(function(){
//angular module
var myApp = angular.module('myApp', ['angularTreeview']);
//test controller
myApp.controller('myController', function($scope){
//test tree model 1
$scope.roleList1 = [
{ "roleName" : "Escapamentos e Catalisadores", "roleId" : "role1", "children" : [
{ "roleName" : "Silencioso Intermediario", "roleId" : "role12", "children" : [
{ "roleName" : "Composicao", "roleId" : "role121", "children" : [
{ "roleName" : "Material 1", "roleId" : "role1211", "children" : [] },
{ "roleName" : "Material 2", "roleId" : "role1212", "children" : [] }
]}
]}
]},
{ "roleName" : "Arquivo 1", "roleId" : "role2", "children" : [] },
{ "roleName" : "Arquivo 2", "roleId" : "role3", "children" : [] }
];
//test tree model 2
$scope.roleList2 = [
{ "roleName" : "Tubos", "roleId" : "role1", "children" : [
{ "roleName" : "Galvanizados", "roleId" : "role11", "collapsed" : true, "children" : [] },
{ "roleName" : "Conducao", "roleId" : "role12", "collapsed" : true, "children" : [
{ "roleName" : "Material 1", "roleId" : "role121", "children" : [
{ "roleName" : "Material 2", "roleId" : "role1211", "children" : [] },
{ "roleName" : "Material 3", "roleId" : "role1212", "children" : [] }
]}
]}
]}
];
//roleList1 to treeview
$scope.roleList = $scope.roleList;
});
})();
(function(l){l.module("angularTreeview",[]).directive("treeModel",function($compile)
{return{restrict:"A",link:function(a,g,c)
{var e=c.treeModel,h=c.nodeLabel||"label",d=c.nodeChildren||"children",
k='<ul><li data-ng-repeat="node in '+e+'">
<i class="collapsed" data-ng-show="node.'+d+'.
length && node.collapsed" data-ng-click="selectNodeHead(node, $event)">
</i><i class="expanded" data-ng-show="node.'+d+'.length && !node.collapsed"
data-ng-click="selectNodeHead(node, $event)"></i>
<i class="normal" data-ng-hide="node.'+d+'.length"></i>
<span data-ng-class="node.selected" data-ng-click="selectNodeLabel(node, $event)">
{{node.'+h+'}}</span>
<div data-ng-hide="node.collapsed" data-tree-model="node.'+d+'
" data-node-id='+(c.nodeId||"id")+" data-node-label="+h+" data-node-children="+d+">
</div></li></ul>";
e&&e.length&&(c.angularTreeview?(a.$watch(e,function(m,b){
g.empty().html($compile(k)(a))},!1),
a.selectNodeHead=a.selectNodeHead||function(a,b){b.stopPropagation&&
b.stopPropagation();b.preventDefault&&b.preventDefault();b.cancelBubble=
!0;b.returnValue=!1;
a.collapsed=!a.collapsed},b.selectNodeLabel=a.selectNodeLabel||function(c,b){ b.stopPropagation&&b.stopPropagation();
b.preventDefault&&b.preventDefault();b.cancelBubble=!0;b.returnValue=!1;
a.currentNode&&a.currentNode.selected&& (a.currentNode.selected=void0;
c.selected="selected";a.currentNode=c}):g.html($compile(k)(a)))}}})})(angular);
everything was working fine before I spllited that file (but I was testing with 1 only module, in other words, no flexy layout, grid, etc. only tree view)
I appreciate any tips/suggestions..
Lucas.
There should only be one module declared to manage the whole page and that module will have same name as ng-app. All the modules you inject should load in page before you try to inject them...can't inject what doesn't exist yet
You inject all other dependent modules in dependency array for the main ng-app page module.
Once you have initialized your 'ng-app` module, use the variable you assign it to to create controllers/directives/services etc.
You have one module you create as app and another as myApp. To use both you need to inject the one that doesn't match ng-app into the one that does

Nested models in Backbone

I am new to Backbone and I have an issue regarding nested models. Here I have data.json where I have following JSON:
[
{
"name": "Project",
"description" : "This is a Peugeot website",
"url" : "http://peugeot.am",
"images" : [
{ "image" : "A", "thumb" : "a" },
{ "image" : "B", "thumb" : "b" },
{ "image" : "C", "thumb" : "c" }
]
},
{
"name" : "Ararat",
"description" : "This is a Ararat website",
"url" : "http://ararat.am",
"images" : [
{ "image" : "A", "thumb" : "a" },
{ "image" : "B", "thumb" : "b" },
{ "image" : "C", "thumb" : "c" }
]
},
{
"name" : "Procredit Bank",
"description" : "This is a Procredit Bank website",
"url" : "http://procredit.am",
"images" : [
{ "image" : "A", "thumb" : "a" },
{ "image" : "B", "thumb" : "b" },
{ "image" : "C", "thumb" : "c" }
]
}
]
In Backbone I am trying to fetch data, but I get empty array.
var myapp = myapp || {};
$(function () {
myapp.Image= Backbone.Model.extend({
initialize: function () {
this.Img = this.get('image');
this.Thumb = this.get('thumb');
}
});
myapp.Images= Backbone.Collection.extend({ model: myapp.Image });
myapp.Item= Backbone.Model.extend({
initialize: function () {
this.Name = this.get('name');
this.Description = this.get('description');
this.URL = this.get('url');
this.subs = new myapp.Images(this.get('images'));
}
});
myapp.Items= Backbone.Collection.extend({
model: myapp.Item,
url: 'content/js/data.json',
parse: function (resp, xhr) { return JSON.parse(resp); }
});
var items = new myapp.Items();
items.fetch();
console.log(items.toJSON());
});
Now, what am I doing wrong above? I need to fetch data to get JSON so to start manipulate with it.
Thanks in advance!
the default support is pretty lacking you would need to get the data for each nested model separately
There are library such as
https://github.com/powmedia/backbone-deep-model
and
http://afeld.github.io/backbone-nested/
Which can be used instead
items.fetch();
console.log(items.toJSON());
Collection.fetch() is an asynchronous operation. It won't produce a response until the request gets back from the server. Try this:
items.fetch().done(function(){
console.log(items.toJSON());
});
You can also use the web inspector in safari/chrome (or firefox debugger / firebug) to monitor network requests and see that your calls are firing successfully (and inspect the responses), or put another console.log statement inside the 'parse' function of your collection.
http://backbonejs.org/#Collection-fetch

Resources