I am trying to create a directive, but for some reason nothing is rendering. The screen is blank.
index.html
<div class="main" ng-controller="MainController">
<div class="container">
<div class="content">
<program-listing listing="program"></program-listing>
</div>
</div>
</div>
<!-- Controllers -->
<script src="js/controllers/MainController.js"></script>
<script src="js/directives/programListing.js"></script>
js/controllers/mainController.js
app.controller('MainController', ['$scope', function($scope) {
$scope.program = {
series: "Sherlock",
series_img: "img/sherlock.jpg",
genre: "Crime drama",
season: 3,
episode: "The Empty Hearse",
description: "Two years after his reported Reichenbach Fall demise, Sherlock, who has been cleared of all fraud charges against him, returns with Mycroft's help to a London under threat of terrorist attack. John has moved on and has a girlfriend, Mary Morstan. Sherlock enlists Molly to assist him, but when John is kidnapped by unknown assailants and is rescued by Sherlock and Mary, John returns to help find the terrorists and an underground plot to blow up the Houses of Parliament during an all night sitting on Guy Fawkes Night.",
datetime: new Date(2014, 11, 31, 21, 00, 00, 00)
};
}]);
js/directives/programListing.js
app.directive('programListing', function(){
return{
restrict: 'E',
scope: {
listing: '='
},
templateUrl: 'js/directives/programListing.html'
};
});
js/directives/programListing.html
<div class="row">
<div class="col-md-3" class="series_img">
{{ listing.series_img }}
</div>
<div class="col-md-6">
<h1 class="series">{{listing.series}}</h1>
<h2 class="episode">{{listing.episode}}</h2>
<p class="description">{{listing.description}}</p>
</div>
<div class="col-md-3">
<ul class="list-group">
<li class="list-group-item"><span>Date:</span> {{listing.datetime | date:'mediumDate' }} </li>
<li class="list-group-item"><span>On air:</span> {{ listing.datetime | date:'EEEE' }} </li>
<li class="list-group-item"><span>Time:</span>{{ listing.datetime | date:'shortTime' }} </li>
<li class="list-group-item"><span>Season:</span> {{listing.season}} </li>
<li class="list-group-item"><span>Genre:</span>{{ listing.genre }} </li>
</ul>
</div>
</div>
Why isn't anything rendering?
templateUrl is an argument to your directive. You should not have it in your scope. Your directive doesn't know what to render!
scope = {...},
templateUrl = '...'
Related
I trying to use directives to show controller data in the my view but nothing displays and there are no errors in the console. I am able to log the data but the data will not show in view. Am I using directives the correct way? How do I show the data in the view? Thank you.
index.html
<body ng-app="GameboardApp">
<div class="header">
<h1 class="logo">GameBoard</h1>
</div>
<div class="main" ng-controller="ScoreController">
<div class="container">
<div class="row" >
<game ng-repeat="score in scores" info="score"></game>
</div>
</div>
</div>
<!-- Modules -->
<script src="js/app.js"></script>
<!-- Controllers -->
<script src="js/controllers/ScoreController.js"></script>
<!-- Directives -->
<script src="js/directives/game.js"></script>
App.js
var app = angular.module('GameboardApp', []);
Controllers
ScoreController:
app.controller('ScoreController', ['$scope', function($scope) {
$scope.scores = [
{
datetime: 1420848000000,
visitor_team: {
city: "Charlotte",
name: "Hornets"
},
home_team: {
city: "New York",
name: "Knicks"
},
period: "Final",
visitor_score: 110,
home_score: 82
},,
...
},
{
datetime: 1420848000000,
visitor_team: {
city: "Orlando",
name: "Magic"
},
home_team: {
city: "Portland",
name: "Trail Blazers"
},
period: "First Quarter",
visitor_score: 13,
home_score: 26
}
];
console.log($scope.scores);
}]);
directives
game.js
app.directive('game', function() {
return {
restrict: 'E',
score: {
info: '='
},
templateUrl: 'js/directives/game.html'
}
})
game.html
<div class="col-sm-4">
<div class="row scorecard">
<p class="period">{{info.period}}</p>
<div class="visitor col-xs-4">
<h2 class="visitor-score">{{info.visitor_score}}</h2>
<h3>
<span class="visitor-city">{{info.visitor_team.city}}</span><br/>
<span class="visitor-name">{{info.visitor_team.name}}</span>
</h3>
</div>
<div class="dash col-xs-3">
<h2>-</h2>
</div>
<div class="home col-xs-4">
<h2 class="home-score">{{info.home_score}}</h2>
<h3>
<span class="home-city">{{info.home_team.city}}</span><br/>
<span class="home-name">{{info.home_team.name}}</span>
</h3>
</div>
</div>
In game.js file, where you have created the directive, you have misspelled the field name. It should be scope not score.
How can I use ng-repeat to loop over data that contains many nested array data?
I have data that will have many "Segments"
Example:
confirm.booking.flightData[0].Segments[0].FlightNumber
confirm.booking.flightData[0].Segments[1].FlightNumber
confirm.booking.flightData[0].Segments[2].FlightNumber
I have done both ng-repeat with angular, and without angular I would end up resorting to javascript that loops over data and creates the html dynamically, but I wish to do this the ANGULAR way.. HOW?
HTML with Angular/Javascript Arrays:
<div class="container-fluid">
<div class="row">
<div class="col-md-4">
<span style="font-weight: bold;">Flight</span>
</div>
<div class="col-md-4">
<span style="font-weight: bold;">Departs</span>
</div>
<div class="col-md-4">
<span style="font-weight: bold;">Arrives</span>
</div>
</div>
<div class="row">
<div class="col-md-4">
{{confirm.booking.flightData[0].Segments[0].FlightNumber}}
</div>
<div class="col-md-4">
({{confirm.booking.flightData[0].Segments[0].DepartureAirport}})
</div>
<div class="col-md-4">
({{confirm.booking.flightData[0].Segments[0].ArrivalAirport}})
</div>
</div>
</div>
Nesting can be done in repeats, but repeating too much in ng-repeats can be costly in terms of performance as angular creates scopes for each element repeated. Hence, filtering data till the perfect abstracted values that you need in terms of html should be done in the js file.
For eg: if u need only segements in the html form do this, or if u need even flight data in html form follow #Rachel's post
<ul data-ng-repeat="item in confirm.booking.flightData[0].Segments">
<li>{{ item.FlightNumber}}</li>
</ul>
Let's say your data is in flightdetails, then you can go about it like this:
<div ng-repeat="a in flightdetails ">
<div ng-repeat="b in a.booking">
<div ng-repeat="c in b.flightdata">
<div ng-repeat="d in c.segments">
{{d.flightnumber}}
</div>
</div>
</div>
</div>
You can use nested ng-repeat to bind your data - see a demo below:
angular.module("app", []).controller("ctrl", function($scope) {
$scope.confirm = {
booking: {
flightData: [{
Segments: [{
FlightNumber: 1
}, {
FlightNumber: 2
}]
}, {
Segments: [{
FlightNumber: 3
}, {
FlightNumber: 4
}]
}]
}
}
// console.log($scope.confirm);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="wrapper" ng-app="app" ng-controller="ctrl">
<div ng-repeat="x in confirm.booking.flightData">
Data {{$index + 1}}:
<div ng-repeat="y in x.Segments">
<div>Flight No: {{y.FlightNumber}}</div>
</div>
<br/>
</div>
</div>
If you want to display only the following:
confirm.booking.flightData[0].Segments[0].FlightNumber
confirm.booking.flightData[0].Segments[1].FlightNumber
confirm.booking.flightData[0].Segments[2].FlightNumber
then you can use limitTo - see demo below:
angular.module("app", []).controller("ctrl", function($scope) {
$scope.confirm = {
booking: {
flightData: [{
Segments: [{
FlightNumber: 1
}, {
FlightNumber: 2
}]
}, {
Segments: [{
FlightNumber: 3
}, {
FlightNumber: 4
}]
}]
}
}
// console.log($scope.confirm);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="wrapper" ng-app="app" ng-controller="ctrl">
<div ng-repeat="x in confirm.booking.flightData | limitTo : 1">
Data {{$index + 1}}:
<div ng-repeat="y in x.Segments">
<div>Flight No: {{y.FlightNumber}}</div>
</div>
<br/>
</div>
</div>
I created an example here:
http://codepen.io/ackzell/pen/ENBymo
It ultimately looks like this, but check the pen as it has some more info:
<ul>
<li ng-repeat="flight in vm.flightData">
<ul>
<li ng-repeat="segment in flight.Segments">
<em>FlightNumber</em> {{ segment.FlightNumber }}
<br />
<em>Departure:</em> {{ segment.DepartureAirport }}
<br />
<em>Arrival:</em> {{ segment.ArrivalAirport }}
</li>
</ul>
</li>
</ul>
Nesting ng-repeats would help, but maybe you want to give your data some treatment first.
I was doing a very quick exercise with angular directives. My code is very simple.
app.js:
var app = angular.module('readingList', []);
app.controller('BooksController', function($scope){
$scope.books = books;
$scope.genres = genres;
})
app.directive('bookGenres', function(){
return {
restrict: 'E',
templateURL: 'partials/book-genres.html'
};
});
var books = [{
title: 'ABCD',
author: 'E. Fgh',
isbn: '123414312341234',
review: 'Hello world',
rating: 4,
genres: {
'non-fiction': true, fantasy: false
}
}];
var genres = ["foo1","bar2","foo2","bar3"];
}
app.html:
<div class="row" ng-controller="BooksController">
<button class="btn btn-default">Create Review</button>
<hr />
<hr />
<ul class="list-unstyled col-sm-8" >
<li class="book row" ng-repeat="book in books">
<aside class="col-sm-3">
<a href="http://www.amazon.com/gp/product/{{book.isbn}}">
<img ng-src="http://images.amazon.com/images/P/{{book.isbn}}.01.ZTZZZZZZ.jpg" alt="" class="full"/>
</a>
<p class="goodRating rating">{{book.rating}}/5</p>
</aside>
<div class="col-sm-9 col-md-8">
<h3>
<a href="https://rads.stackoverflow.com/amzn/click/com/0553593714" rel="nofollow noreferrer">
{{book.title}}
</a>
</h3>
<cite class="text-muted">{{book.author}}</cite>
<p>{{book.review}}</p>
<!-- Put Genre Here -->
<book-genres></book-genres>
<ul class="list-unstyled">
<li ng-repeat="(genre, state) in book.genres">
<span class="label label-primary" ng-show="state === true">
{{genre}}
</span>
</li>
</ul>
</div>
</li>
</ul>
</div>
book-genres.html:
<ul class="list-unstyled">
<li ng-repeat="(genre, state) in book.genres">
<span class="label label-primary" ng-show="state === true">
{{genre}}
</span>
</li>
</ul>
Everything renders with the view except my book-genres directive. For reason, it doesn't work. I have checked the documentation. I checked other similar examples and nothing. If I can't get this directive to work, rendering out the other components such as the image is going to be a problem. I also checked the path of the partials views as well.
There's a couple possibilities here. You need to be sure to inject $scope into your controller:
app.controller('BooksController', ['$scope', function($scope) {
// do stuff
}]);
book.genres is not defined anywhere, so your ng-repeat has no items to display.
templateURL is also incorrect, it should be templateUrl.
please am very new new to angular and am trying to do something i don't know if its possible. I have a json data and i want to render the option on click of an item. What i want to achieve is to show models of a phone on click of the name, and on click of a phone model show all the phone parts. But whenever i click on a phone i get undefined in my console.
my app.js file
(function(){
var app=angular.module('repairshop',[]);
app.controller('phoneController',function($scope){
this.phones = [
{
name: 'Apple',
model: [{ name: 'Iphone 5'}, {name: 'Iphone 6'},{name: 'Iphone 6s'}],
part: [{name:'ear phones'},{name:'external speakers'},{name:'Screen Guard'},{name:'Charger'}]
},
{
name: 'Samsung',
model: [{ name: 'S4'}, {name: 'S5'},{name: 'S6'}],
part: [{name:'ear phones'},{name:'external speakers'},{name:'Screen Guard'},{name:'Charger'}]
},
{
name: 'Nokia',
model: [{ name: 'Lumia'}, {name: '3310'},{name: 'Asha'}],
part: [{name:'ear phones'},{name:'external speakers'},{name:'Screen Guard'},{name:'Charger'}]
},
{
name: 'Blackberry',
model: [{ name: 'Passport'}, {name: 'Touch 10'},{name: 'Asha'}],
part: [{name:'ear phones'},{name:'external speakers'},{name:'Screen Guard'},{name:'Charger'}]
}
];
$scope.loadModels=function(phone)
{
var phone=phone.name;
console.log (phone);
}
});
})();
My Html View
<div class="phones_wrapper row">
<!--begin container-->
<div class="container">
<form class="" action="#" method="post" ng-controller="phoneController as phone" >
<div class="row">
<div class="col-md-3 phone_display center" ng-repeat="p in phone.phones">
<label>
<input type="radio" ng-click="loadModels(phone)" ng-model="phone.name" name="phone" ng-value="{{p.name}}" />
<img src="http://placehold.it/200x200">
</label>
<p class="text text-center phone_name">{{p.name}}</p>
</div>
</div>
</form>
</div>
<!--begin container-->
</div>
Here is a simple example plnkr on how you can click on the list of the items you describe to view more details such as models and parts.
<body ng-controller="MainCtrl">
<ul>
<li ng-repeat="phone in phones" ng-click="showModels = true">{{phone.name}}
<ul ng-show="showModels">
<li ng-repeat="model in phone.model" ng-click="showParts = true">{{model.name}}
<ul ng-show="showParts">
<li ng-repeat="part in phone.part">
{{part.name}}
</li>
</ul>
</li>
</ul>
</li>
</ul>
</body>
Basically what you have to do is add repeaters and ng-click events to expand the content. I am pretty sure that from this example you will be able to fix it with your own styling and markup.
Edit:
A better example where you can toggle the viewing of models and parts.
<body ng-controller="MainCtrl">
<ul>
<li ng-repeat="phone in phones" ng-click="showModels = !showModels; $event.stopPropagation()">{{phone.name}}
<ul ng-show="showModels">
<li ng-repeat="model in phone.model" ng-click="showParts = !showParts; $event.stopPropagation()">{{model.name}}
<ul ng-show="showParts">
<li ng-repeat="part in phone.part">
{{part.name}}
</li>
</ul>
</li>
</ul>
</li>
</ul>
</body>
I found it, i changed the loadModels function to
$scope.loadModels=function(phone)
{
phone.parent=phone.name;
console.log (phone);
}
and also changed the phone to p based on #Praneeth Gudumasu recommendation. Thank you
it should be like this
<div class="col-md-3 phone_display center" ng-repeat="p in phone.phones">
<label>
<input type="radio" ng-click="loadModels(p)" ng-model="p.name" name="phone" ng-value="{{p.name}}" />
<img src="http://placehold.it/200x200">
</label>
<p class="text text-center phone_name">{{p.name}}</p>
</div>
you should use the repeating object inside the repeating template and not the scope object(in your case variable "p" not "phone")
My custom directive is not working:
html:
<body ng-controller="StoreController as store">
<ul class="list-group">
<li class="list-group-item" ng-repeat="product in store.products">
<div>
<h3>
<product-title></product-title>
</h3>
...
javascript.app:
...
app.directive('productTitle', function(){
return {
restrice: 'E',
templateUrl: 'product-title.html'
};
});
...
and my product-title.html:
{{product.name}}
<em class="pull-right"> {{product.price | currency}}</em>
in my html page i cant see the product name and product price.
I am new in this subject :)
what should i do to make it work?
please help me.
++thanks everyone for yours answers, it is works! i tried for 3 days to find an answer.. and you did it in 5 min.. thanks! :)++
Couple of issues:
restrict is spelled wrong
Templates for html should have one root, so you should do something like this
<div>
{{product.name}}
<em class="pull-right"> {{product.price | currency}}</em>
</div>
Here is the complete running code for your directive in this JSBin
JS
angular
.module('app', [])
.controller('AppController', function ($scope) {
$scope.store = {
products: [
{ id: 1, price: 132, name: 'abc' },
{ id: 2, price: 127, name: 'def' },
{ id: 3, price: 112, name: 'mno' },
{ id: 4, price: 145, name: 'xyz' }
]
};
})
.directive('productTitle', function(){
return {
restrict: 'E',
templateUrl: 'product-title.html'
};
});
HTML
<div ng-controller='AppController'>
<ul class="list-group">
<li class="list-group-item" ng-repeat="product in store.products">
<h3>
<product-title></product-title>
</h3>
</li>
</ul>
</div>
<script id="product-title.html" type="text/ng-template">
{{product.name}}
<em class="pull-right"> {{product.price | currency}}</em>
</script>