I have a problem with scope property of directive that doesn't render want to render in directive view.
app.js
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl',
controllerAs: 'main'
})
main.js
angular.module('todayfmApp')
.controller('MainCtrl', ['$scope', function ($scope) {
this.formsetup = [];
this.formsetup.title = "Find Your Break";
}]);
mainController View - where Form Setup: {{main.formsetup.title}} is rendering properly
<h2>Form Setup: {{main.formsetup.title}}</h2>
<section class="home-banner">
<carousel-partial></carousel-partial>
<overlay-form formsetup="main.formsetup.title"></overlay-form>
directive
angular.
module('directives').
directive('overlayForm', function() {
return {
restrict: 'E',
scope: {
formsetup: '='
},
controller: [ '$http', '$scope',
function OverlayFormController($http, $scope) {
var self = this;
self.getResponseData = function(){
$http.get('data/form-data.json').then(function(response) {
self.formdata = response.data;
});
}
this.logResponseData = function() {
console.log(self.formdata);
}
this.getResponseData();
}
],
controllerAs: 'Ctrl',
bindToController: true,
templateUrl: 'scripts/directives/overlay-form/overlay-form.template.html',
};
});
Directive View
<div class="overlay-form">
<h3>{{formsetup.title}}</h3>
Problem is with template binding.It should be:(when you use controllerAs you need to refer view elements with the alias name)
<div class="overlay-form">
<h3>{{Ctrl.formsetup.title}}</h3>
</div>
And directive HTML code should be:
<overlay-form formsetup="main.formsetup"></overlay-form>
Please check Plunker for more understanding of how it works.
Related
I am new to angularjs and I was trying to create custom directive and for that I was following steps from https://www.youtube.com/watch?v=R_okHflzgm0 I did exactly what was shown here but for some reason img src is blank I dont know what is wrong in my code
//created new app
var myApp=angular.module('myFirstApp', ['ngRoute']);
//configured routing
myApp.config(['$routeProvider', function($routeProvider){
$routeProvider
.when('/home', {
templateUrl: 'views/home.html'
})
.when('/directory', {
templateUrl: 'views/directory.html',
controller: 'NinjaController'
}).otherwise({
redirectTo: '/home'
});
}]);
//custom directive
myApp.directive('randomNinja', [function(){
return{
restrict: "E",
scope: {
ninjas: '=',
title: '='
},
templateUrl: 'views/random.html',
controller: function($scope){
$scope.random = Math.floor(Math.random()*4);
}
};
}]);
//controller
myApp.controller('NinjaController', ['$scope', '$http', function($scope,$http){
$http.get('data/ninjas.json').then(function(response){
$scope.ninjas=response.data;
}, function(error){
console.log(error);
})
$scope.removeNinja=function(ninja){
var ninjaRemoved=$scope.ninjas.indexOf(ninja);
$scope.ninjas.splice(ninjaRemoved, 1)
}
$scope.addNinja=function(){
$scope.ninjas.push({
name: $scope.newNinja.name,
belt: $scope.newNinja.belt,
rate: parseInt($scope.newNinja.rate),
available:true
})
$scope.newNinja.name='',
$scope.newNinja.belt='',
$scope.newNinja.rate=''
}
//image links
Inspect view from browser
JSON data file
Home with custom directive and random view
In my angular app, I have created a custom directive for a navbar, which controller takes in $stateParams to access a variable called lang, as so:
.config(function($stateProvider, $urlRouterProvider, LANG) {
$urlRouterProvider
.otherwise('/' + LANG['EN'].shortName);
$stateProvider
.state('proverb-list', {
url: '/:lang',
templateUrl: 'components/proverb-list/proverb-list.html',
controller: 'ProverbListCtrl as vm'
})
.state('proverb-single', {
url: '/:lang/:proverbId',
templateUrl: 'components/proverb-single/proverb-single.html',
controller: 'ProverbCtrl as vm'
});
});
When I access the state proverb-list, the controller named ProverbListCtrl does see $stateParams.lang correctly, but my navbar directive cannot. When I console.log($stateParams) all I get is an empty object.
This navbar is outside my ui-view:
<navbar proverbial-navbar></navbar>
<div ui-view></div>
<footer proverbial-footer></footer>
Is that the problem? How can I access the actual $stateParams inside my directive?
EDIT: directive code below, as asked:
(function() {
'use strict';
angular
.module('proverbial')
.directive('proverbialNavbar', directive);
function directive() {
var directive = {
restrict: 'EA',
templateUrl: 'components/shared/navbar/navbar.html',
scope: {
},
link: linkFunc,
controller: Controller,
controllerAs: 'vm',
bindToController: true
};
return directive;
function linkFunc(scope, el, attr, ctrl) {
}
}
Controller.$inject = ['LANG', 'ProverbFactory', '$stateParams'];
function Controller(LANG, ProverbFactory, $stateParams) {
var vm = this;
vm.languages = LANG;
console.log($stateParams);
vm.currentLang = LANG[$stateParams.lang.toUpperCase()];
activate();
function activate() {
vm.alphabet = ProverbFactory.getAlphabet();
}
}
})();
You should not access $stateParams in this directive when it is independent of the state. Since your navbar is outside of the ui-view, its controller can be called before the ui-router has initialized the $stateParams of the state you are interested in. Remember that your navbar controller is called only once, when the navbar is initialized and not every time the state changes.
Alternative: What you can do is turn your currentLang field into a function. The function can retrieve the value from the $stateParams when needed:
vm.currentLang = function() { return LANG[$stateParams.lang.toUpperCase()] };
Make sure you change currentLang to currentLang() everywhere in your template.
I am building a single page app with Angular JS. The problem is the custom directive mySlider cannot access the scope of the controllers I assign to the template. Is there a way to solve this problem? Here are my files
index.html
<script src="js/dishesapp.js"></script>
<div ng-view></div>
partials/dishestemplate.html
<div my-slider></div>
directives/slider.html
<div id="dishsliderholder">
<ul class="bxslider">
<li class="dishdetails" ng-repeat="dish in dishes">
<div class="item">
<div class="title">{{dish.name}}</div>
<div class="description">{{dish.description}}</div>
</div>
</li>
</ul>
</div>
dishesapp.js
var dishesApp = angular.module('dishesApp', ['ngRoute']);
dishesApp.config(function ($routeProvider) {
$routeProvider
.when('/', {templateUrl: 'partials/default.html'})
.when('/Noodles', {templateUrl: 'partials/dishtemplate.html', controller: 'NoodlesCtrl'})
.when('/Rolls', {templateUrl: 'partials/dishtemplate.html', controller: 'RollsCtrl'})
.when('/Pancakes', {templateUrl: 'partials/dishtemplate.html', controller: 'PancakesCtrl'})
.when('/Rice', {templateUrl: 'partials/dishtemplate.html', controller: 'RiceCtrl'})
.when('/FamilyStyle', {templateUrl: 'partials/dishtemplate.html', controller: 'FamilyStyleCtrl'})
.when('/Others', {templateUrl: 'partials/dishtemplate.html', controller: 'OthersCtrl'})
.otherwise({redirectTo: '/'});
});
dishesApp.controller('NoodlesCtrl', function ($scope, $http) {
$scope.mycategory = "Noodles";
$http.get("http://www.blabla.com/Data/dishes.php").success(function (response) {
$scope.dishes = response.records;
});
});
dishesApp.controller('RollsCtrl', function ($scope, $http) {
$scope.mycategory = "Rolls";
$http.get("http://www.blabla.com/Data/dishes.php").success(function (response) {
$scope.dishes = response.records;
});
});
……………..
dishesApp.directive('mySlider', function() {
return {
restrict: 'A',
templateUrl: 'directives/slider.html',
link: function (scope, element, attrs) {
angular.element( document.querySelector('.bxslider')).bxSlider();
angular.element( document.querySelector('#dishsliderholder')).css("background-size", getSliderHolderBackgroundSize());
}
};
});
I finally figured out the problem. The slider object was called before the DOM finish rendering so the slider shows nothing. I use $timeout to call the slider post render. Here is how I did it
dishesApp.directive('mySlider', function ($timeout) {
return {
restrict: 'A',
replace: true,
templateUrl: 'directives/slider.html',
link: function (scope, element, attrs) {
$timeout(function () {
angular.element(document.querySelector('.bxslider')).bxSlider();
angular.element(document.querySelector('#dishsliderholder')).css("background-size", getSliderHolderBackgroundSize());
});
}
};
});
Since the directive is not isolated, you can access all the controllers' scope variables inside a directive link function.
Your code is working. As #Rhumbori commented http://jsfiddle.net/w5mh927p/ is perfectly working.
Try adding a line inside link function: console.log(scope) and check what all is present on scope in your developer tools console. https://www.dropbox.com/s/q3tmgapcxn8e71p/Screenshot%202015-05-31%2002.17.33.png?dl=0
I am trying to bring to my homepage a custom directive which will print me some output.
In the network tab in my devtools I just saw that my controller loads twice.
controller:
var homeController = function($log,leaguesFactory){
var self = this;
self.leagues = [];
leaguesFactory.loadLeagues()
.then(function(leagues){
self.leagues = leagues.data.Competition;
});
self.message= 'test message';
};
directive:
var leaguesTabs = function(){
return {
restrict : 'E',
templateUrl : 'app/home/leagues-tabs.tpl.php',
scope: {
leagues: '='
},
controller: 'homeController',
controllerAs: 'homeCtrl'
};
};
ui-router states:
$stateProvider
.state('home',{
url : '/',
templateUrl : 'app/home/home.tpl.php',
controller : 'homeController',
controllerAs: 'homeCtrl'
})...
I just want to use my homeCtrl in the directive, but it seems that the state provider loads it also and make it load twice. If I remove the controller from the directive then I don't get access to the homeCtrl, if I remove the homeCtrl from the stateprovider than I don't have access in the home.tpl.php
home.tpl.php:
<div>
<leagues-tabs></leagues-tabs>
</div>
any idea?
Actually problem related to next steps:
ui-router start handling url '/'
ui-router create an instance of 'homeController'
ui-router render the view 'app/home/home.tpl.php'
Angular see usage a custom directive - 'leagues-tabs'
'leagues-tabs' directive create an instance of 'homeController'
'leagues-tabs' render the view 'app/home/home.tpl.php'
You can follow any of next possible solutions:
Change controller for 'leagues-tabs' to something special
Remove controller usage from ui-router state definition
You can try this one http://plnkr.co/edit/LG7Wn5OGFrAzIssBFnEE?p=preview
App
var app = angular.module('app', ['ui.router', 'leagueTabs']);
UI Router
app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/leagues');
$stateProvider
.state('leagues', {
url: '/leagues',
templateUrl: 'partial-leagues.html',
controller: 'LeaguesController',
controllerAs: 'ctrl'
});
}]);
Controller
app.controller('LeaguesController', ['$http', function($http) {
var self = this;
$http.get('leagues.json').success(function(data){
self.leagues = data;
})
}]);
View
<div>
<league-tabs leagues="ctrl.leagues"></league-tabs>
</div>
Directive
var leagueTabs = angular.module('leagueTabs', []);
leagueTabs.directive('leagueTabs', function(){
return {
restrict : 'E',
templateUrl : 'partial-league-tabs.html',
scope: {
leagues: '='
},
controller: 'LeagueTabsController',
controllerAs: 'leagueTabs'
}
});
leagueTabs.controller('LeagueTabsController', function($scope){
var self = this
$scope.$watch('leagues', function(leagues){
self.leagues = leagues;
})
})
Directive View
<div>
<ul ng-repeat="league in leagueTabs.leagues">
<li>{{league.name}}</li>
</ul>
</div>
I'm new to AngularJS. Can someone help me why the following routing will not work? I have a custom directive that submits a user form. After submission, it should navigate to the success page.(views/success.html).
I'm getting an error upon submission. TypeError: Cannot read property
'path' of undefined
If I simply try navigate to "/index.html#/success" on the address bar, it will not redirect to the success page, so I'm suspecting it is a routing issue but I can't seem to understand the cause of it. Any help would be greatly appreciated!
var myApp = angular.module('myApp', ['ngRoute', 'myControllers', 'loginDirective'])
.config(function ($routeProvider) {
$routeProvider.when("/home", {
templateUrl: 'index.html',
controller: 'myApp'
}).when("/success", {
templateUrl: 'views/success.html',
controller: 'myApp'
})
// If no route is selected then use the 'home' route.
.otherwise({ redirectTo: '/home' });
});
// Directive - Modifies HTML behaviour.
var myDirectives = (function () {
var myDirectives = angular.module('loginDirective', []);
// directive() is a factory method to create directives.
myDirectives.directive('login', function () {
return {
restrict: 'A',
scope: {
},
link: function ($scope, elem, attrs, ctrl, $location) {
$scope.submit = function() {
console.log("I clicked on submit");
$location.path("/success");
}
},
templateUrl: function (element, attr) { return 'views/loginForm.html' },
}
});
return myDirectives;
}());
// Controller - dispatches inputs and outputs.
var myControllers = (function () {
var myControllers = angular.module('myControllers', []);
// Controllers are defined by the controller function.
myControllers.controller('AppCtrl', ['$scope', '$routeParams','$location', function ($scope, $routeParams, $location) {
$scope.title = "Sign in";
}]);
return myControllers;
}());
index.html
<!DOCTYPE html>
<html>
<body ng-app='myApp' ng-controller="AppCtrl" class="container">
<div login></div> //custom directive
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular-route.min.js"></script>
<script src="js/app.js"></script>
</body>
</html>
$location needs to be injected in the directive definition, not in the link
function, e.g.
// directive() is a factory method to create directives.
myDirectives.directive('login', ['$location', function ($location) {
...
}]);
Also you don't need to use a separate module for controllers, directive, etc. In other words, there only needs to be one angular.module('...') call
Your whole code can be simplified as
// define the app
var app = angular.module('myApp', ['ngRoute']);
// app configuration block
app.config(['$routeProvider',
function ($routeProvider) {
$routeProvider.when("/home", {
templateUrl: 'index.html',
controller: 'myApp'
}).when("/success", {
templateUrl: 'views/success.html',
controller: 'myApp'
})
// If no route is selected then use the 'home' route.
.otherwise({ redirectTo: '/home' });
}]);
// definition block for 'AppCtrl' controller
app.controller('AppCtrl', ['$scope',
function ($scope) {
$scope.title = "Sign in";
}]);
// definition for 'login' directive
app.directive('login', ['$location',
function ($location) {
return {
restrict: 'A',
scope: {
},
link: function (scope, element, attrs) {
scope.submit = function() {
console.log("I clicked on submit");
$location.path("/success");
}
},
templateUrl: 'views/loginForm.html'
}
}]);