Accessing variables set in the controller from the directive - angularjs

I am trying to avoid the use of $scope in my angular controller (as suggested in a best practices tutorial). In the controller, I'm setting testVariable. In the directive, I'm returning the template, including testVariable, but this added variable does not output any value. This code is based on what I've found in the AngularJS documentation.
Below is my javascript code:
(function(angular) {
'use strict';
angular.module('docsSimpleDirective', [])
.controller('Controller', ['$scope', function($scope) {
var _controller = this;
$scope.customer = {
name: 'Naomi',
address: '1600 Amphitheatre'
};
_controller.testVariable = "Test Variable!"
}])
.directive('myCustomer', function() {
return {
template: 'Name: {{customer.name}}<br />Address: {{customer.address}}<br />Value Here: {{ testVariable }}'
};
});
})(window.angular);
Here is the HTML:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-directive-simple-production</title>
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="docsSimpleDirective">
<div ng-controller="Controller">
<div my-customer></div>
</div>
</body>
</html>
I set up a plunkr for this here.

If you use controllerAs and bindToController it will simplify your directive and then access testVariable
angular.module('docsSimpleDirective', [])
.controller('Controller', [function () {
this.customer = {
name: 'Naomi',
address: '1600 Amphitheatre'
};
this.testVariable = "Testing data here!"
}])
.directive('myCustomer', function () {
return {
template: 'Name: {{$ctrl.customer.name}}<br />Address: {{$ctrl.customer.address}}<br />Value Here: {{ $ctrl.testVariable }}',
controller: 'Controller',
controllerAs: '$ctrl',
bindToController: true
};
});
You can further simplify your directive if you use .component to create docsSimpleDirective

Related

How isolate scope by attribute with value type uuid

I want to make a dashboard with widgets. The data (json object) that must be displayed on widgets cam from server by ajax request at every n seconds. Every widget has uuid type identifier. I have tryed using directive isolated scope, but it didn't work form me with uuid type. Here is my Plunker example.
How to make this code working?
Or maybe there is better ways to acomplish this goal with angularjs ?
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="dashboard">
<div ng-controller="widgetController as ctrl">
<widget id="ctrl.cbdf9d33-8d7a-43f7-a8b5-5b011edd2402"></widget>
<widget id="ctrl.5ed23c32-a443-45eb-932e-8ff1d23a912f"></widget>
<widget id="ctrl.2de16396-88a3-48cd-b42a-bc30bdd80064"></widget>
</div>
</body>
</html>
script.js
(function(angular) {
'use strict';
angular.module('dashboard', [])
.controller('widgetController', ['$interval', '$http', function($interval, $http) {
var vm = this;
var updateWidgetsLoop = $interval(function() {
$http({
method: 'GET',
url: 'server.json'
}).then(function successCallback(response) {
var widgets = response.data;
angular.forEach(widgets, function(widget, key) {
vm[key] = widget;
});
});
}, 5000);
}])
.directive('widget', function() {
return {
restrict: 'E',
scope: {
id: '='
},
template: '<div>{{id.value}}</div>',
};
});
})(window.angular);
server.json
{
"cbdf9d33-8d7a-43f7-a8b5-5b011edd2402" : {"value": 10},
"5ed23c32-a443-45eb-932e-8ff1d23a912f" : {"value": 20},
"2de16396-88a3-48cd-b42a-bc30bdd80064" : {"value": 30}
}
Change you html code
<widget id="ctrl.cbdf9d33-8d7a-43f7-a8b5-5b011edd2402"></widget>
to
<widget id="ctrl['cbdf9d33-8d7a-43f7-a8b5-5b011edd2402']"></widget>
It should work. Good Luck :-)
Working Plunker https://plnkr.co/edit/SmJtaItdB7lrgxu0GbiP?p=preview
Hope it solved you problem :-)

In AngularJS, if the child directive cannot access it's immediate parent's scope then would it inherit its nearest, non-isolated ancestor's scope?

I have two examples in favor of the above statement -
1) When using $scope (http://plnkr.co/edit/kFM77mVReS7AUwZsNzCV?p=preview) -
<!DOCTYPE html>
<html>
<head>
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<script>
angular
.module('myApp', [])
.directive('directive1', function() {
return {
controller: ['$scope', function($scope) {
$scope.name = 'Directive1';
}]
};
})
.directive('directive2', function() {
return {
controller: ['$scope', function($scope) {
$scope.name = 'Directive2';
}],
scope: {}
};
})
.directive('directive3', function() {
return {
template: 'I am {{name}}'
};
});
</script>
</head>
<body ng-app='myApp'>
<directive1>
<directive2>
<directive3>
</directive3>
</directive2>
</directive1>
</body>
</html>
2) When using controllerAs(http://plnkr.co/edit/zmIRa1t87ZIMDS6X5rNo?p=preview)-
<!DOCTYPE html>
<html>
<head>
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<script>
angular
.module('myApp', [])
.directive('directive1', function() {
return {
controller: function() {this.name = 'Directive1';},
controllerAs: 'ctrl1'
};
})
.directive('directive2', function() {
return {
controller: function() {this.name = 'Directive2';},
controllerAs: 'ctrl2',
transclude: true,
template: '<ng-transclude></ng-transclude>',
scope: {}
};
})
.directive('directive3', function() {
return {
template: 'I am {{ctrl1.name}}'
};
});
</script>
</head>
<body ng-app='myApp'>
<directive1>
<directive2>
<directive3>
</directive3>
</directive2>
</directive1>
</body>
</html>
The output of both the codes is - I am Directive1 which shows that directive3 inherits the scope of directive1(it won't access the scope of directive2 since it has an isolated scope) which proved me wrong in assuming that an isolated scope would break the inheritance chain between its parent directive and its child directives and thus none of its child directive would be able to access the scope of any of its ancestor directives.
Am I missing something here or is my concept of scope inheritance completely wrong?
The output <...> proved me wrong in assuming that an isolated scope would break the inheritance chain between its parent directive and its child directives
The proof itself is wrong. This behaviour is specific to template-less directives and is similar to transclusion. In the code above directive1 has no own scope, and $scope.name = 'Directive1' is set on root scope. And both directive1 and directive2 are compiled with root scope because they have no templates and no own scopes.
The said assumption will be correct if directives have their own templates, e.g.:
.directive('directive2', function() {
return {
template: '<directive3>'
controller: ['$scope', function($scope) {
$scope.name = 'Directive2';
}],
scope: {}
};
})
Use scope:true in all your 3 directives and it will able to access all scopes of the parents
Note: scope:true will inherit the properties from the parent, but scope:{} will not inherit the properties from the parent.
<!DOCTYPE html>
<html>
<head>
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<script>
angular
.module('myApp', [])
.directive('directive1', function() {
return {
controller: ['$scope', function($scope) {
$scope.name = 'Directive1';
}],
scope: true
};
})
.directive('directive2', function() {
return {
controller: ['$scope', function($scope) {
$scope.name = 'Directive2';
}],
scope: true
};
})
.directive('directive3', function() {
return {
template: 'I am {{name}}',
scope: true
};
});
</script>
</head>
<body ng-app='myApp'>
<directive1>
<directive2>
<directive3></directive3>
</directive2>
</directive1>
<br>
<directive1>
<directive3></directive3>
</directive1>
<br>
<directive2>
<directive3></directive3>
</directive2>
</body>
</html>

Access AngularJs directive variable inside controller

I'm little bit new to Angularjs. What I want is access "$scope.myVar" variable inside 'myController' controller. It would be great help if you can provide a solution.
angular.module('myDirective', [])
.controller('myController', ['$scope', function ($scope) {
}])
.directive('myDirective', function () {
return {
scope: {
myVar: '='
},
controller: function ($scope) {
$scope.myVar = 'xyz';
alert($scope.myVar);
}
};
});
<html lang="en-US">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script type="text/javascript" src="newjavascript.js"></script>
<body ng-app="myDirective">
<div ng-controller="myController">
<my-directive></my-directive>>
</div>
</body>
</html>
You just create a myVar variable in your controller and pass it to the directive using my-var attribute.
In your myController, Define myVar as
$scope.myVar= "Hello"
I your DOM, pass it to the directive as
<my-directive my-var="myVar"></my-directive>
Since you are using two way binding, any changes made to myVar by the directive are available in your controller.
You can put a watch on myVar to track the changes.
angular.module('myDirective', [])
.controller('myController', ['$scope', function ($scope) {
$scope.show = function() {
alert($scope.myVar);
};
}])
.directive('myDirective', function () {
return {
scope: {
myVar: '='
},
controller: function ($scope) {
$scope.myVar = 'xyz';
alert($scope.myVar);
$scope.$parent.myVar = $scope.myVar; // here you can access the controller scope by using $parent
}
};
});

Angular: $routeProvider

I am having issues with setting up my routing. I am getting the following error in my console. My folder 'partials' is named correctly and my files are named correctly. Any help?
Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.3.12/$injector/modulerr?p0=demoApp&p1=Error%3…s%2Fthomasjanszen%2Fcodinghouse%2FAngular%2Fjs%2Fangular.min.js%3A17%3A381)
<!DOCTYPE html>
<html lang="en" ng-app="demoApp">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div class="container">
<div ng-view=""></div>
</div>
<script src="js/angular.min.js"></script>
<script>
var demoApp = angular.module('demoApp', ['']);
demoApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/view1', {
templateUrl: 'partials/view1.html',
controller: 'SimpleController'
}).
when('/view2', {
templateUrl: 'partials/view2.html',
controller: 'SimpleController'
}).
otherwise({
redirectTo: '/view1'
});
}]);
// demoApp.controller('SimpleController', function($scope){
// $scope.customers=[
// {name: 'name1', city: 'Cincinnati'},
// {name: 'name2', city: 'NYC'},
// {name: 'name3', city: 'Denver'},
// {name: 'name4', city: 'Chicago'}
// ];
// $scope.addCustomer = function(){
// $scope.customers.push(
// {
// name: $scope.newCustomer.name,
// city: $scope.newCustomer.city
// });
// };
// });
</script>
</body>
</html>
From angular 1.2 onwards, if you want angular routing you need to
Include the JS file : <script src="angular-route.js"></script>
You can obtain angular-route.js for your version of angular (1.3.12) here: https://code.angularjs.org/1.3.12/
provide ngRoute as a dependency, i.e.
change this:
var demoApp = angular.module('demoApp', ['']);
to this
var demoApp = angular.module('demoApp', ['ngRoute']);
For details please refer to the AngularJS Developers Doc - migration guide
You need to inject 'ng-route' as a dependency in your module
var demoApp = angular.module('demoApp', ['ng-route']);

Angular routeProvider

I just followed a tutorial about angular on youtube but i'm not able to execute the code due to an routeProvider problem. I tried to include the good link for angular-route.js but it's still doesn't work...
I show you the code:
<!DOCTYPE html>
<html ng-app="demoApp">
<head>
<title>Tuto Angular</title>
</head>
<body>
<div>
<div ng-view=""></div>
</div>
<script src="angular.min.js" type="text/javascript"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular-route.js"></script>
<script type="text/javascript">
var demoApp = angular.module('demoApp', ['ng-route']);
demoApp.config(function ($routeProvider){
$routeProvider
.when('/',
{
controller: 'SimpleController',
templateUrl: 'Partials/View1.html'
})
.when('/view2',{
controller: 'SimpleController',
templateUrl: 'Partials/View2.html'
})
.otherwise({ redirectTo: '/' });
});
demoApp.controller('SimpleController', function ($scope){
$scope.customers = [
{name:'John Smith', city:'Phoenix'},
{name:'John Doe', city:'New York'},
{name:'Jane Doe', city:'Chicago'}
];
$scope.addCustomer = function (){
$scope.customers.push(
{
name: $scope.newCustomer.name,
city: $scope.newCustomer.city
});
};
});
</script>
</body>
When i look into the console it returns me that:
Uncaught Error: [$injector:modulerr]
If you have any idea you're welcome !
change:
var demoApp = angular.module('demoApp', ['ng-route']);
to
var demoApp = angular.module('demoApp', ['ngRoute']);
When injecting a dependency into our app module,use camelCase and not snake-case
Here, use ngRoute and not ng-route
See: https://stackoverflow.com/a/11934258/1177295
In Angular we need to use camelCase for Dependency injection and Directive definition in java Scripts files and snake-case in the HTML pages where directive is used
Lets take if you have directive myFirstDirective in Directive defination you will use
demoApp.directive(myFirstDirective, function () {
return{}
});
In the HTMl you will use
<my-first-directive></my-first-directive>
You have only included it inside the function. You have to inject the serivce into the config method and make sure the ng-route is included in the app references

Resources