I am trying to make working ngDialog downloaded from here: ngDialog
Here is my code:
<script src="http://cdnjs.cloudflare.com/ajax/libs/ng-dialog/0.2.3/js/ngDialog.min.js"></script>
My directive:
directives = angular.module("mainApp", ['ngDialog']);
directives.directive('caseList', function () {
return {
restrict: 'AE',
require: 'ngModel',
link: function (scope, elem, attrs, ngModel, ngDialog) {
......
ngDialog.open({
template: '<p>my template</p>',
plain: true
});
I am getting an error:
Uncaught TypeError: Cannot read property 'open' of undefined
Checking ngDialog object and it is undefined.
What exactly am I doing wrong?
Here what was wrong. ngDialog should have been injected into the directive definition:
Directive:
directives.directive('caseList', function (**ngDialog**) {
No need to inject it into Link function.
Related
Having trouble with a reCaptcha module in a Polymer 1 app.
I can use this module once (on the register form) but if I try to use it on any other component results in an error: Uncaught Error: reCAPTCHA has already been rendered in this element.
Initially thought the problem was because I loaded the recaptcha script inside the module so I moved that to index.html. But the problem continues to persist.
Tried using grecaptcha.reset() in various places to unload the widget so it can be rendered in other components.
Inside recaptcha-module-html:
<dom-module id="recaptcha-module">
<template>
<div class="captcha-container">
<div id="captcha"></div>
</div>
</template>
<script>
Polymer({
is: "recaptcha-module",
ready: function () {
this.recaptchaCallback = this.recaptchaCallback.bind(this)
this.recaptchaExpired = this.recaptchaExpired.bind(this)
window.recaptchaCallback = this.recaptchaCallback
window.recaptchaExpired = this.recaptchaExpired
},
attached: function () {
grecaptcha.render('captcha', {
'sitekey': {SITE_KEY_HERE}
'size': 'compact',
'callback': 'recaptchaCallback',
'expired-callback': 'recaptchaExpired'
});
},
recaptchaCallback: function () {
this.fire('recaptcha-success')
},
recaptchaExpired: function () {
this.fire('recaptcha-expired')
}
});
</script>
</dom-module>
Loading the recaptcha script in index.html:
<script src="https://www.google.com/recaptcha/api.js">
</script>
How I try to load the recaptcha-module in other components:
<link rel="import" href="recaptcha-module.html">
...
<recaptcha-module></recaptcha-module>
I expect that the module can be imported and used in multiple form components with but doing so causes an error and the widget refuses to be loaded more than once.
This issue was caused because the module did not assign a unique ID to the placeholder reCaptcha element. In order to fix the issue I created a property called elementid that could be used to give each render of the reCaptcha element a unique ID.
<dom-module id="recaptcha-module">
<template>
<div class="captcha-container">
<div class="captcha" id="[[elementid]]"></div>
</div>
</template>
<script>
Polymer({
is: "recaptcha-module",
properties: {
elementid : String,
captchastyle : String
},
ready: function () {
this.recaptchaCallback = this.recaptchaCallback.bind(this)
this.recaptchaExpired = this.recaptchaExpired.bind(this)
window.recaptchaCallback = this.recaptchaCallback
window.recaptchaExpired = this.recaptchaExpired
},
attached: function () {
grecaptcha.render(this.elementid, {
'sitekey': {MY_SITE_KEY},
'size': this.captchastyle,
'callback': 'recaptchaCallback',
'expired-callback': 'recaptchaExpired'
});
},
recaptchaCallback: function () {
this.fire('recaptcha-success')
},
recaptchaExpired: function () {
this.fire('recaptcha-expired')
}
});
</script>
</dom-module>
Then you can import the module and use the custom element anywhere else by giving it a unique ID. Like so:
<recaptcha-module elementid="UNIQUE_ID" captchastyle="normal"></recaptcha-module>
I'm in the middle of refactoring an old project to use custom directives, and I'm already running into a problem. I'm just trying to make a simple directive and build from there. I have a logger function in my directive's link function that just runs a console.log. I'm not sure what I'm missing here, and I'm sure it's something simple. Here's my directive:
'use strict';
(function() {
angular
.module('sigFig')
.directive('myDirective', myDirective);
function myDirective(sigFigFactory) {
var directive = {
restrict: 'E',
replace: 'true',
templateUrl: 'Directives/directiveTemplate.html',
link: link,
compile: compile
};
return directive;
function link(scope, element, attrs) {
scope.logger = function() {
console.log('DING!!!');
}
}
function compile(scope, element, attrs) {
console.log('I AM A COMPILE FUNCTION');
}
}
})();
The HTML template for it is just:
<button ng-click="logger()">CLICK ME</button>
And I'm calling it in my HTML like this:
<my-directive></my-directive>
The button appears and that console.log in my compile works, but the ng-click does not. What is it I'm missing? Thanks in advance!
Add scope to directive variable: scope:{},
function myDirective(sigFigFactory) {
var directive = {
scope:{},
restrict: 'E',
replace: 'true',
templateUrl: 'Directives/directiveTemplate.html',
link: link,
compile: compile
};
return directive;
I have never created an angular application without a controller. So I'm positive that that is your issue here.
Example of your code with a controller.
html:
<body ng-app='sigFig' ng-controller='ctrl'>
<my-directive></my-directive>
</body>
js:
(function() {
angular.module('sigFig', [])
.controller('ctrl', function($scope){
$scope.itemH = 'hahaha'
})
.directive('myDirective', myDirective);
function myDirective() {
return {
restrict: 'E',
template: '<button ng-click="logger()">{{item}}</button>',
link: function link(scope, element, attrs) {
scope.item = "Logger Click Me";
scope.logger = function() {
alert('logger')
}
}
};
function compile(scope, element, attrs) {
console.log('I AM A COMPILE FUNCTION');
}
}
})();
In my main html, I have a view which loads templates.
<div data-ng-view></div>
It loads a html whenever the link is clicked.
app.config(["$routeProvider", function ($routeProvider) {
'use strict';
$routeProvider
.when("/", {
templateUrl: "events.html"
});
}]);
On this page (template) , I have a directive which loads another html file
app.directive('ngPost', function () {
'use strict';
return {
restrict: 'A',
templateUrl: 'postbox.html'
};
});
I then use this directive on my events.html page by using <div data-ng-Post></div>
In postbox, I have two input fields and a button
<input type="text" id="user" data-ng-model="username" />
<input type="text" id="mess" data-ng-model="message"/>
<button data-ng-click="Add(eventid-1, username, message)">Post</button>
Upon clicking the button, I have some operations, then I try to clear the input fields, but I cannot. Method here :
$scope.Add = function (index, uname, msg) {
var a = {user: uname, message: msg, time: new Date()};
$scope.data[index].messages.push(a);
$scope.message = ''; // clearing here
$scope.username ='';
};
The clearing does not happen, I do not know why. My controller that has this Add method wraps the <div data-ng-view></div>in the main html file so it is the outermost controller and should have access to all $scope models inside. Why does it not work?
Note that the operations before the clearing works with no problems
Your add method is in the parent scope. The parent's scope cannot see it's children, it works the other way around. The message and username properties are defined in the directive's child scope. From a child you can reference parent properties, but not the other way around.
If you add scope: false and transclude: false to your directive, it won't create it's own scope and instead use its parent's scope, so your directive would look something like this:
angular.module('app', []).controller("myController",myController);
function myController($scope){
var ctrl = this;
ctrl.hello ="Hello"
};
angular.module('app').directive("childThing", function() {
return {
template: '<div>{{message}}</div><div>{{username}}</div>',
scope: false,
transclude: false,
controller: function($scope) {
$scope.username="Mike Feltman"
$scope.message="Hi Mike"
}
}
})
and you can access the elements that the directive adds to the scope from the parent like this:
<div ng-controller="myController as ctrl">
{{username}} in the parent.
<div>{{ctrl.hello}}</div>
<child-thing></child-thing>
</div>
Update using your template:
{{username}} in the parent.
{{ctrl.hello}}
Javascript:
function myController($scope){
var ctrl = this;
ctrl.hello ="Hello"
$scope.add = function() {
alert($scope.username)
}
};
angular.module('app').directive("childThing", function() {
return {
template: '<input type="text" id="user" data-ng-model="username" /><input type="text" id="mess" data-ng-model="message"/>',
scope: false,
transclude: false,
}
})
I have a directive
configModule.directive('iMemoryDiv',function () {
return {
restrict: 'E',
scope: {},
replace: true,
templateUrl: '/memoryDiv.html',
link: function(scope, el, attrs) {
scope.iObj = scope.$parent[attrs.bIObject];
if(angular.isDefined(scope.iObj)){
getSummary(scope.iObj);
}
function getSummary(iObj){
}
}
};
}
);
and I am calling it from html by passing an object attribute
<i-memory-div b-i-object="app"></i-memory-div> //here app is declared in a respective controller
but, here directive is getting loaded before the controller where value for 'app' is getting assigned.So scope.iObj = scope.$parent[attrs.bIObject] is always giving me undefined.
How can make directive load after the app value is getting assigned ??
Isn't it easier doing it this way:
configModule.directive('iMemoryDiv',function () {
return {
restrict: 'E',
scope: {
'bIObject': '=',
'getParentObject': '&'
},
replace: true,
templateUrl: '/memoryDiv.html',
link: function(scope, el, attrs) {
scope.$watch('bIObject', function(newValue) {
if(angular.isDefined(newValue)) {
getSummary(scope.getParentObject({name: newValue}));
}
});
function getSummary(iObj){
}
}
};
}
Or do you need more from the parent scope??
You could give your directive an isolated scope and add bIObject as a scope property:
scope: {
bIObject: '=',
},
you could then put your code in the controller: rather than link:
Use $observe service in link function,like this
if(attrs. bIObject) {
attrs.$observe('bIObject', function(value) {
console.log(value);
})
}
I have a question. I coded a HTML page with an angularjs directive
this is my code
<menufileupload visible="rightVisible" alignment="right">
<input type="text" ng-model='expr'/>
<!--Other stuff-->
</menufileupload>
I'm trying to use a $watch to check any change in the text field
$scope.$watch(...) only worked when the text field is out of the
directive. So I think that I have to create a $watch in the directive. I did that. But it didn't work.
Directive
app.directive("menufileupload", function() {
return {
restrict: "E",
template: "<div>bla</div>",
link: function(scope, elem, attrs) {
scope.$watch('expr', function(obj) {
alert("it changed");
}, true);
}
};
});
Thanks for your help
You have a template in your directive, so everything inside it will be replaced by that <div> tag.
It works fine if you remove the template. I made a codepen example of your code:
http://codepen.io/argelius/pen/jEzQVJ
angular.module('test', [])
.directive('menufileupload', function () {
return {
restrict: "E",
link: function(scope, elem, attrs) {
scope.$watch('expr', function(obj) {
alert("it changed");
}, true);
}
};
});
If you want your input element to be shown inside the directive DOM you should use the ngTransclude directive. Please check it out in the documentation.