I am trying to build a simple custom directive, but it is constantly throwing me an error. I have included my sample code in the below jsFiddle link. Can anyone help me with where exactly I went wrong.
[https://jsfiddle.net/sridharspeaks/65vnj4dz/][1]
Thanks,
Sridhar
this is fixed plunker :
http://plnkr.co/edit/KTFFLc0QdmunQ4i8AT8o?p=preview
i think there is a problem with
the case of your directive and controller name ( i put all to lower case, don't have too much time sorry)
you didn't use ng-controller="mycontainercontroller" to tell angular with controller to use
don't inject $scope on directive only in controller's directive :
html :
<head>
<script src="http://code.angularjs.org/1.2.1/angular.js"></script>
<script src="script.js"></script>
</head>
<body>
<div ng-controller="mycontainercontroller">
<mycontainer></mycontainer>
</div>
</body>
and JS :
angular.module('myApp', []).
directive('mycontainer', function() {
return {
restrict: 'E',
scope: {},
controller: 'mycontainercontroller',
template: '<div><input ng-model="container"></div><div>output : {{container}}</div>'
}
}).controller('mycontainercontroller', ['$scope', function($scope) {
$scope.container = 123;
}]) ;
There are two issues. One is with the fiddle, the script must run before window load, so set the following:
Second, don't inject $scope into the directive. You only have access to the directive scope in the link function.
Updated fiddle: https://jsfiddle.net/65vnj4dz/5/
Related
I'm still very new at this and this is my first attempt to making an app without following any guide. For some reason my output in the webpage is {{$scope.products}} instead of the actual values. Can anyone tell my why it won't load the angular code from the controller?
index.html
<<!doctype html ng-app="MyFirstApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainController as ctrl">
{{ctrl.name}}
{{"Hello World"}}
</body>
</html>
app.js
var app = angular.module('MyFirstApp', [])
.controller('MainController', function(){
this.name = "Joe";
});
Your snippet contains some errors:
<!doctype html ng-app="MyFirstApp"> : ngApp directive is too high. Please put it in the <body> tag at least.
ng-controller="MainController as ctrl": if it is your very first AJS example, be aware that controllerAs is a best practice, but a bit advanced. This choice will condition slightly the controller code.
{{products.title}}: products is an array!
... .controller('MainController',[$scope function($scope){: the second argument of controller method is an array, so between $scope and function a comma is needed. In your case the array must be: ['$scope',function($scope){...}]. For more info pls see https://docs.angularjs.org/guide/di
$scope.products = [...]; : in order to avoid controllerAs antipattern you must use this.products.
Please update your code.
you need to put the dependancy to your controller between '' and
you are missing some thing after $scope
.controller('MainController',['$scope',function($scope){
}]);
and there are no iterate for the array in your controller to be bind in html
var app = angular.module('MyFirstApp', [])
.controller('MainController', function(){
this.name = "Joe"
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="MyFirstApp" ng-controller="MainController as ctrl">
{{ctrl.name}}
</div>
AngularJS documentation can be quite confusing.
Assigning values to the $scope is considered a bad practice. This is one of the things that the controllerAs syntax solves. So instead of adding the products to $scope.products -- add them to this.name.
Then in your view you will access them with {{ctrl.name}}
I hope this helps.
I am trying to load a template file in an AngularStrap popover, however I am having trouble using $templateCache. I seem to be a step further back than the other SO questions, hence this seemingly double one.
Following the API docs I added a <script type="text/ng-template" id="popoverTemplate.html"></script> right before the closing </body> tag. When I use <div ng-include="'popoverTemplate.html'"></div> on my page, I get nothing. If I try using console.log($templateCache.get("popoverTemplate.html")) I get "$templateCache is not defined", which leads me to assume I am missing a crucial step. However, I can't find how to do it in the docs or other SO questions.
EDIT:
Injecting the service was the missing link. However, when I inject the service, the controller's other function no longer works, but if you inject al the function's parameters the working code becomes:
(function() {
"use strict";
angular.module("app").controller("managerController", ["$scope", "imageHierarchyRepository", "$templateCache", function ($scope, imageHierarchyRepository, $templateCache) {
imageHierarchyRepository.query(function(data) {
$scope.hierarchies = data;
});
var template = $templateCache.get("popoverTemplate.html");
console.log(template);
}]);
})();
To use the template script tag . You have to insert it inside the angular application. That is inside the element with the ng-app attribute or the element used to bootstrap the app if you don't use the ng-app tag.
<body ng-app="myapp">
<div ng-template="'myTemplate.html'"></div>
<script type="text/ng-template" id="myTemplate.html">
// whate ever
</script>
</body>
If you want to retrieve the template on a component of the application then you need to inject the service where you want to consume it:
controller('FooCtrl', ['$templateCache', function ($templateCache) {
var template = $templateCache.get('myTemplate.html');
}]);
Or
controller('FooCtlr', FooCtrl);
FooCtrl ($templateCache) {};
FooCtrl.$inject = ['$templateCache'];
EDIT
Do not register two controllers with the same name because then you override the first one with the last one.
(function() {
"use strict";
angular.module("app").controller("managerController",["$scope", "imageHierarchyRepository", "$templateCache", function ($scope, imageHierarchyRepository, $templateCache) {
var template = $templateCache.get("popoverTemplate.html");
console.log(template);
imageHierarchyRepository.query(function(data) {
$scope.hierarchies = data;
});
}]);
})();
Small addition: Although there are few ways to achieve your goals, like wrapping your whole HTML in <script> tags and all that, the best approach for me was to add the $templateCache logic into each Angular directive. This way, I could avoid using any external packages like grunt angular-templates (which is excellent but overkill for my app).
angular.module('MyApp')
.directive('MyDirective', ['$templateCache', function($templateCache) {
return {
restrict: 'E',
template: $templateCache.get('MyTemplate').data,
controller: 'MyController',
controllerAs: 'MyController'
};
}]).run(function($templateCache, $http) {
$http.get('templates/MyTemplate.html').then(function(response) {
$templateCache.put('MyTemplate', response);
})
});
Hope this helps!
I am newbie to Angularjs. I am trying to create simple directive with the following code:
View:
<html>
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<user-info></user-info>
</div>
</body>
</html>
Controller:
myapp = angular.module("myapp", []);
myapp.directive('userInfo', function() {
var directive = {};
directive.restrict = 'E'; /* restrict this directive to elements */
directive.template = "My first directive: ";
return directive;
});
I am following this Tutorial to learn directive
http://tutorials.jenkov.com/angularjs/custom-directives.html
I am getting error:
http://errors.angularjs.org/1.3.14/$injector/modulerr?p0=myApp&p1=Error%3A%20%5B%24injector%3Anomod%5D%20http%3A%2F%2Ferrors.angularjs.org%2F1.3.14%2F%24injector%2Fnomod%3Fp0%3DmyApp%0A%20%20%20%20at%20Error%20(native)%0A%20%20%20%20at%20http%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.14%2Fangular.min.js%3A6%3A417%0A%20%20%20%20at%20http%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.14%2Fangular.min.js%3A21%3A412%0A%20%20%20%20at%20a%20(http%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.14%2Fangular.min.js%3A21%3A53)%0A%20%20%20%20at%20w.bootstrap%20(http%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.14%2Fangular.min.js%3A21%3A296)%0A%20%20%20%20at%20http%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.14%2Fangular.min.js%3A35%3A46%0A%20%20%20%20at%20s%20(http%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.14%2Fangular.min.js%3A7%3A302)%0A%20%20%20%20at%20g%20(http%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.14%2Fangular.min.js%3A34%3A399)%0A%20%20%20%20at%20ab%20(http%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.14%2Fangular.min.js%3A38%3A135)%0A%20%20%20%20at%20d%20(http%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.14%2Fangular.min.js%3A17%3A381
Here is my codepen link
http://codepen.io/anon/pen/NGNKxz
You have error in the name of your app :
myapp = angular.module("myApp", []); // not 'myapp'
Add Your Directive
You need to add the directive to your html like so
<script src="path/to/your/directive.js"></script>
or if your working from one module you will link to the main module. But please restructure your app like this it will keep code up to standard and clean.
I have a git hub repo where I am building an app in this structure here. Best of luck.
Note
You are using angular min. Min is great for production because its small and faster to load but your in development at the moment so use the full version so you can capture errors better with the browser console.
Looks like you did not declare the controller myCtrl. Your directive looks fine.
myapp.controller('myCtrl', function() {
});
Is it the current version of your html file ?
Because you might need to link your controller, between head tags, insert :
<script src="the js file which contains your controller"></script>
or
<script>Your controller</script>
Angular Structural Question
I am new to angular.js and am just wondering how to go about performing a certain situation.
So basically, what I have got is a container:
<div ng-controller="ContainerController">
<container></container>
</div>
And the container controller and directives.
<script type="text/javascript" src="ContainerController.js"></script>
<script type="text/javascript" src="ContainerDirectives.js"></script>
Now the directives replaces the <container> tag with an example html: <example>{{ data }}</example>
Now within the scope of the ContainerController I have defined data as a string. (This is all example purposes). However when the directive accesses replaces it, it is unable to find the variable, due to scope.
The reason that this happens is because the ContainerDirective script's scope is not within the ContainerController scope. Meaning it is unable to access the variable.
Im just not sure on structure practices for these kinds of situations. Where do I put everything so the ContainerDirective can access the ContainerController scope.
I hope i have explained everything good enough
EDIT:
Test.js
(function(){
angular.module('test', []);
})();
TestController.js
(function(){
angular
.module('test')
.controller('TestController', [
'$scope',
TestController
]);
function TestController($scope) {
$scope.test = 'test';
}
})();
TestDirective.js
(function(){
angular.module('test').directive('test', function () {
return {
replace: true,
templateUrl: 'src/test/view/test.html',
link: function (scope, element, attrs) {
}
};
});
})();
test.html
<example>ClickMe</example>
index.html - body
<body ng-app="App" layout="row" ng-controller="TestController as page">
<test></test>
<script src="src/test/Test.js"></script>
<script src="src/test/TestController.js"></script>
<script src="src/test/TestDirective.js"></script>
<script type="text/javascript">
angular
.module('App', ['test']);
</script>
</body>
For reasons I have renamed certain variables and deleted a lot of data, but this is the core, and I am struggling to see anything wrong with this.
Error: [$interpolate:noconcat] Error while interpolating: abc/{{test}}
Strict Contextual Escaping disallows interpolations that concatenate multiple expressions when a trusted value is required.
So I figured out what was wrong in the end. Basically angular wont allow iframe of another location to be printed unless you first:
Give them the full url.
Then allow external url as a trusted website.
TO do this I had to basically add:
in the Test.js
angular.module('test', []).config(function($sceDelegateProvider) {
$sceDelegateProvider.resourceUrlWhitelist($sceDelegateProvider.resourceUrlWhitelist().concat([
'http://www.test.com/**'
]));
});
This basically took my whitelist and concatinated the new url to it.
Then inside test.html:
<example><iframe ng-src={{src}}></iframe></example>
I have put up my code at jsbin: http://jsbin.com/fewom/1/edit
If any one can guide me, what am I doing wrong there. I have specified scope to be isolated inside myDirective with scope: {} but still when i write myProperty inside my directive in html I am able to read myProperty.
I was using AngularJS https://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.min.js
When i changed my library to it started to work,
https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.3/angular.js
then I have tried,
Angular JS version 1.2.16
https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js
and
Angular JS version 1.3.0-beta.5
https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.5/angular.min.js
and the problem for isolated scoping shows up again.
You don't have a controller, so nothing ties your directive to your html.
Change your js to this (I just added a blank controller):
angular.module('myApp', [])
.directive('myDirective', function() {
return {
restrict: 'A',
scope: {}
};
})
.controller('ctrl', function (){
});
and in your html, change to this (referenced the controller):
<html ng-app="myApp" ng-controller='ctrl'>