I am studying the Localization example at the bottom of AngularJS home page.
I am looking at the source of the page and try to do exactly what the demo shows me.
However, I can't seem to fire up the demo code. The lines that confused me the most are:
<span class="pull-right"
js-fiddle="tabs.html components.js beers.js" module="components"> ...
<div app-run="tabs.html" module="components-us" class="well"> ...
Because I don't recognise app-run or js-fiddle to be AngularJS syntax (or is it?). Anyway, the demo app doesn't fire up. Could you please help me take a look?
Here is the code I COPY & PASTE from AngularJS home page and put in index.html: (change the header base and libraries to your directory accordingly)
index.html
<!doctype html>
<html ng-app>
<head>
<meta charset="utf-8">
<!-- ************IMPORTANT !! change this to your directory************ -->
<base href='http://localhost/angularjs/localization/' />
<link rel="stylesheet" href="../bootstrap/css/bootstrap.css">
<script src="../bootstrap/js/bootstrap.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"></script>
</head>
<body>
<div class=" row example">
<div class="span1 app-source" app-source="tabs.html components.js beers.js" annotate="tabs.annotation" module="components"></div>
<div class="span4">
<span hint></span>
<span class="pull-right" js-fiddle="tabs.html components.js beers.js" module="components"></span>
<div class="tabs-spacer"></div>
<h4>Locale: {{ 'US' }}</h4>
<div app-run="tabs.html" module="components-us" class="well"></div>
<div class="tabs-spacer"></div>
<h4>Locale: {{ 'SK' }}</h4>
<div app-run="tabs.html" module="components-sk" class="well"></div>
</div>
</div>
<script>
angular.module('components-us', ['components', 'ngLocal.us']);
angular.module('components-sk', ['components', 'ngLocal.sk']);
</script>
<script type="text/ng-template" id="tabs.html">
<tabs>
<pane title="Localization">
Date: {{ '2012-04-01' | date:'fullDate' }} <br>
Currency: {{ 123456 | currency }} <br>
Number: {{ 98765.4321 | number }} <br>
</pane>
<pane title="Pluralization">
<div ng-controller="BeerCounter">
<div ng-repeat="beerCount in beers">
<ng-pluralize count="beerCount" when="beerForms"></ng-pluralize>
</div>
</div>
</pane>
</tabs>
</script>
<script id="beers.js">
function BeerCounter($scope, $locale) {
$scope.beers = [0, 1, 2, 3, 4, 5, 6];
if ($locale.id == 'en-us') {
$scope.beerForms = {
0: 'no beers',
one: '{} beer',
other: '{} beers'
};
} else {
$scope.beerForms = {
0: 'žiadne pivo',
one: '{} pivo',
few: '{} pivá',
other: '{} pív'
};
}
}
</script>
<script id="components.js">
angular.module('components', []).
directive('tabs', function() {
return {
restrict: 'E',
transclude: true,
scope: {},
controller: function($scope, $element) {
var panes = $scope.panes = [];
$scope.select = function(pane) {
angular.forEach(panes, function(pane) {
pane.selected = false;
});
pane.selected = true;
}
this.addPane = function(pane) {
if (panes.length == 0) $scope.select(pane);
panes.push(pane);
}
},
template:
'<div class="tabbable">' +
'<ul class="nav nav-tabs">' +
'<li ng-repeat="pane in panes" ng-class="{active:pane.selected}">'+
'{{pane.title}}' +
'</li>' +
'</ul>' +
'<div class="tab-content" ng-transclude></div>' +
'</div>',
replace: true
};
}).
directive('pane', function() {
return {
require: '^tabs',
restrict: 'E',
transclude: true,
scope: { title: '#' },
link: function(scope, element, attrs, tabsCtrl) {
tabsCtrl.addPane(scope);
},
template:
'<div class="tab-pane" ng-class="{active: selected}" ng-transclude>' +
'</div>',
replace: true
};
})
</script>
</body>
</html>
Also, where are app-run and js-fiddle from? I can't figure out if they are features belong to AngularJS or what.
app-run and js-fiddle are custom Angular directives -- i.e., directives they wrote to help run the AngularJS home page (hence the reason they are in the file aptly named homepage.js).
Here is a working plnkr of the demo.
Related
I have this function:
$scope.link = function (){
return [{
value: 'https://www.google.it',
text: 'go to details'
}
]
}
i want pass this function in parent controller to the child, i tried to do this:
.directive('card', function(){
var TPL = `<div class="card" style="width: 18rem">
<div class="card-body">
<p>{{c.paragrafo}}</p>
<h4 class="card-title">{{c.title}}</h4>
<h6 class="card-subtitle mb-2 text-muted">{{c.paragrafo2}}</h6>
<p class="card-text"></p>
<a class="card-link">{{c.link()}}</a>
</div>
</div>`
var directive = {
restrict: 'E',
template: TPL,
scope: {
paragrafo: '#',
title: '#',
paragrafo2: '#',
link: '&'
},
controller: ctrlFn,
controllerAs: 'c',
bindToController: true
};
return directive;
function ctrlFn(){
}
})
and in index.html:
<body ng-app="app" ng-cloak>
<div ng-controller="MainCtrl">
<div class="container">
<div class="row">
<div class="col" ng-repeat="demo in demos">
<card title="{{demo.title}}"
paragrafo="{{demo.paragrafo}}"
paragrafo2="{{demo.paragrafo2}}"
link="link()"
></card>
</div>
</div>
</div>
</div>
</body>
But the body of the function returns to me, how can i fix this?
I want to see the link text "go to details" and when I click on it it takes me to the google page
I'm trying really hard, but I can't find where is my problem.
I created a custom directive and it should iterate some HTML to draw the right content on the screen.
The problem is that my ng-repeat does not iterate my array. I search on stackoverflow but what I found didn't help me.
Here is my directive (it's in an external file):
app.directive('logtab', function(){
return {
restrict: 'E',
templateUrl: 'view/templates/log-tab.html',
replace: true,
controller: ['$scope', 'api', function($scope, api) {
$scope.logState = false;
$scope.logData = [1,2,3,4];
$scope.loadLog = function() {
api.doRequest({
path : $scope.path,
method : "GET",
broadcast : BK_LOG
});
};
var bk = $scope.$on(BK_LOG, function(key, value){
$scope.logState = true;
console.log($scope.logData);
bk();
});
}]
};
});
And here is the directive HTML that will be rendered:
<md-tab ng-click="loadLog()" label="{{i18n['REVISIONS']}}">
<div layout="row" layout-align="center" layout-padding ng-show="!logState">
<div layout="column">
<div>
<md-progress-circular md-mode="indeterminate" md-diameter="130"></md-progress-circular>
</div>
<div>
{{i18n['LOG_LOAD']}}
</div>
</div>
</div>
<div layout="row" ng-show="logState" layout-padding>
<div layout="column">
<div ng-repeat="xyz in logData">
{{xyz}}
SOME CONTENT HERE
</div>
</div>
</div>
</md-tab>
Thanks in advance!
I removed other components from your directive code and kept it at bare minimum. The code is working fine as expected. Please see below.
Index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Index</title>
</head>
<body ng-app="myApp" >
<logtab></logtab>
<script src="angular.js" type="text/javascript "></script>
<script src="app.js" type="text/javascript "></script>
</body>
</html>
app.js
var myApp = angular.module('myApp', []);
myApp.directive('logtab', function(){
return {
restrict: 'E',
templateUrl: 'log-tab.html',
replace: true,
controller: ['$scope', function($scope) {
$scope.logState = false;
$scope.logData = [1,2,3,4];
console.log('hi');
}]
};
});
log-tab.html
<div>
{{logData}}
<div layout="row">
<div layout="column">
<div ng-repeat="xyz in logData">
{{xyz}}
</div>
</div>
</div>
</div>
Please use a couple of console.log's to identify the exact location. I suspect that there must be some thing wrong with the other parts of the directive or may be logState is set to false??
You can always separate the controller from the directive:
app.directive('logtab', function(){
return {
restrict: 'E',
templateUrl: 'view/templates/log-tab.html',
replace: true,
scope: {
log: '='
}
};
});
Then in your controller
app.controller('MyController', ['$scope', 'api', function($scope, api) {
$scope.logTab = {
state: false,
data: [1, 2, 3, 4],
loadLog: function() {
api.doRequest({
path : $scope.path,
method : "GET",
broadcast : BK_LOG
});
}
};
var bk = $scope.$on(BK_LOG, function(key, value){
$scope.logTab.state = true;
console.log($scope.logTab.data);
bk();
});
}]);
Then change your HTML to:
<md-tab ng-click="log.loadLog()" label="{{i18n['REVISIONS']}}">
<div layout="row" layout-align="center" layout-padding ng-show="!log.state">
<div layout="column">
<div>
<md-progress-circular md-mode="indeterminate" md-diameter="130"></md-progress-circular>
</div>
<div>
{{i18n['LOG_LOAD']}}
</div>
</div>
</div>
<div layout="row" ng-show="log.state" layout-padding>
<div layout="column">
<div ng-repeat="xyz in log.data">
{{xyz}}
SOME CONTENT HERE
</div>
</div>
</div>
</md-tab>
And call it with
<logtab log="logTab"></logtab>
Updated my answer based on OP's explanation.
Created a fiddle here: https://jsfiddle.net/frishi/bzbbo5da/14/
I simplified the directive definition a little, removed the api part of it.
I also changed the directive's template to include the ng-repeat part of it.
//....
restrict: 'E',
template: `<p><div ng-repeat="xyz in logData">
{{xyz}}
SOME CONTENT HERE
</div></p>`,
replace: false,
scope: true, // <- needs to be set
//....
You are missing the scope parameter in the directive definition object. You have to set it to scope: true for your directive's template to be able to access a variable defined on the directive controller's scope.
Plunker Demo
I created two custom directives for template usage in a ng-repeater.
Outside of the ng-repeater, the directives work. Once I try to dynamically load the directives in a ng-repeater, the directives do not load at all. In fact - when use "Inspect Element" - the {{expressions}} do not dynamically update.
Here is how my ng-repeater looks:
<div ng-repeat="section in content">
<section class="section-{{ section.block }}" block="{{ section.block }}">{{ section.block }}</section>
</div>
I am calling the directives via restrict: C
Here is one of the directives:
.directive('sectionHeader', function() {
return {
restrict: 'EAC',
scope: {
block: '='
},
templateUrl: 'sectionHeader.html'
};
})
Here is the templateURL:
<div class="container">
<figure class="icon">
<img class="img-fluid" ng-src="{{ block.icon }}" title="App Icon">
</figure>
<h1>{{ block.title }}</h1>
<figure class="hero">
<img class="img-fluid" ng-src="{{ block.image }}" title="App">
</figure>
</div>
And a snippet of the JSON:
$scope.content = [
{
block: 'header',
icon: 'http://www.placehold.it/128x128?text=PLACEHOLpng',
title: 'Header Title',
image: 'http://www.placehold.it/1200x675?text=PLACEHOLDER'
},...
];
Now, I believe The templateUrls are not loading because it seems like the directives are being executed before ng-repeat get its content. What I believe I need to do is to execute the directives after ng-repeat receives the content. I am not sure where to start.
Thanks.
You can achieve that using $compile function.
See example on plunker.
Create general directive with $compile.
.directive('section', function($compile) {
return {
restrict: 'EAC',
scope: {
block: '='
},
link:function(scope,elem){
if(scope.block)
$compile(elem.html('<section-'+scope.block.block+' block="block">'))(scope);
}
};
})
Create two different directive.
.directive('sectionHeader', function() {
return {
restrict: 'EAC',
scope: true,
templateUrl: 'sectionHeader.html'
};
})
.directive('sectionHundred', function() {
return {
restrict: 'EAC',
scope: true,
templateUrl: 'sectionHundred.html'
};
});
And usage
<div ng-repeat="section in content">
<section block="section"></section>
</div>
JSON data:
[
{
block: 'header',
icon: 'http://www.placehold.it/128x128?text=PLACEHOLpng',
title: 'Header Title',
image: 'http://www.placehold.it/1200x675?text=PLACEHOLDER'
},
{
block: 'hundred',
icon: 'http://www.placehold.it/128x128?text=PLACEHOLpg',
title: 'Hundred Title',
content: 'Hundred Content',
link: {
copy: 'Link Copy',
title: 'Link Title',
url: '#'
},
image: 'http://www.placehold.it/1200x675?text=PLACEHOLDER'
}
];
You cannot use directive by passing their name dynamically.
But a possible workaround is to use ng-switch instead :
<div ng-repeat="section in content">
<div ng-switch="section.block">
<section ng-switch-when="header" class="section-header" block="{{ section.block }}">{{ section.block }}</section>
... another ng-switch...
</div>
See this post for more details
Though #stepan-kasyanenko gave me a correct answer - I further removed extra lines of code not needed to minimize the build.
New Plunker Link with answer added.
home.html
Old:
<div ng-repeat="section in content">
<section block="section"></section>
</div>
New:
<section ng-repeat="section in content" block="section"></section>
I placed the ng-repeat in the <section> that calls the directive
directives
.directive('sectionHeader', function() {
return {
restrict: 'EAC',
replace: true,
scope: true,
templateUrl: 'sectionHeader.html'
};
});
I added replace: true, to both directives because the ng-repeat builds out another <section> inside of the <section ng-repeat> element
Thank you #stepan-kasyanenko
Question: Why doesn't my simple directive have access to its controller when the element is used on certain pages?
Additional Info: The directive works on the main page. The HTML I could not use my directive on is called using ui-view and is included below.
<div ui-view></div>
Directive:
var postcardAppDirectives = angular.module('postcards.directives', ['postcards.controllers']);
postcardAppDirectives.directive('postcardLink', function () {
return {
restrict: "AE",
template: '<div class="well">{{ ctrl.ownerObj.user }}</div>',
controller: 'postcardLinkController as ctrl'
}
});
Controller:
var PostcardsControllers = angular.module('postcards.controllers', ['postcards.factories', 'postcards.services']);
PostcardsControllers.controller('postcardLinkController', [function ()
this.ownerObj = {
"user": 'test_owner',
"pointofthis": 'inane testing'
}
}]);
HTML (Does Not Work):
<div ng-controller="DashboardAccountController as infoCtrl" class="container full-container">
<!------------------ DIRECTIVE REFERENCE HERE -------->
<postcard-link></postcard-link>
<h1>
<small>Welcome</small>
<username-text></username-text>
</h1>
<img ng-show="infoCtrl.user.member_profile.profile_image" ng-src="{{ infoCtrl.user.member_profile.profile_image }}"
style="min-height:100px;height:100px;" alt='profileImage'/>
<button type="button" class="btn btn-link col-md-offset-2" ng-click="infoCtrl.loadPage()">Modify Account</button>
<div class="row">
...
HTML (Working Fine)
<ng-include src="'static/app/carousel/_carousel.html'"></ng-include>
<postcard-link></postcard-link>
<div class="container">
<section style="text-align: center">
<h1>How It Works</h1>
I see you used different module that's why one module don't know another module directive. you should use same module.
Like:
js:
var app = angular.module('postcards', []);//add dependencies in []
app.directive('postcardLink', function () {
return {
restrict: "AE",
template: '<div class="well">{{ ctrl.ownerObj.user }}</div>',
controller: 'postcardLinkController as ctrl'
}
});
app.controller('postcardLinkController', [function () {
this.ownerObj = {
"user": 'test_owner',
"pointofthis": 'inane testing'
}
}]);
use as usual html:
<postcard-link></postcard-link>
In my directive the example I was looking at here uses <a href="#" ... to put the new image in the container div. I've tried to create that same functionality in my directive but when I click my images it doesn't change my pictBox div. Could I be missing stuff in my css file? Why is the background-image text there? This is my directive:
app.directive('smallPictureBox', [function(){
return {
restrict: 'CA',
replace: false,
transclude: false,
scope: {
index: '=index',
item: '=itemdata'
},
template: '<img src="{{item.url}}"/>',
link: function(scope, elem, attrs) {
if (parseInt(scope.index)==0) {
angular.element(attrs.options).css({'background-image':'url('+ scope.item.url +')'});
}
elem.bind('click', function() {
var src = elem.find('img').attr('src');
angular.element(attrs.options).css({'background-image':'url('+ scope.item.url +')'});
});
}
}
}]);
This is what my html looks like:
<div class="shadow">
<div class="pictureBox">
<div id="pictBox">
<img ng-src="{{primaryImage.url}}">
</div>
</div>
<div class="lowerPictureBox">
<div ng-repeat="image in item.images" options='#pictBox' itemdata='image' index="$index" class="smallPictureBox">
<img ng-src="{{image.url}}">
</div>
</div>
</div>
How can make it so that when I click a picture in the lowerPictureBox it displays it in the pictureBox?
Although i could not replicate your total example but i have a set up a small working code which displays image on top when u click bottom image this could help you
<!DOCTYPE html>
<html ng-app="demo">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.js"></script>
</head>
<body ng-controller="main">
<div class="shadow">
<div class="pictureBox">
<div id="pictBox">
<img ng-src="{{primaryImage.url}}">
</div>
</div>
<div class="lowerPictureBox">
<div small linksrc="primaryImage"></div>
</div>
</div>
<script>
var app = angular.module("demo", []);
app.controller('main', function ($scope) {
$scope.primaryImage = { url: '' };
});
app.directive('small', [function () {
return {
scope: { src: '=linksrc' },
replace:true,
template:"<img ng-src='http://angularjs.org/img/AngularJS-small.png'>",
link: function (scope, elem, attrs) {
elem.bind("click", function () {
scope.src.url = 'http://angularjs.org/img/AngularJS-small.png';
scope.$apply();
});
}
}
}]);
</script>
</body>
</html>