I created directive for google location autocomplete input filed, I include the google api.js file in the index page, the weird thing is if I put the directive in the index.page it works, but if I put it in the other pages, it doesn't work.
directive:
angular.module('ecom').controller('googleMapsCtr', ['$scope',
function($scope) {
console.log($scope.locationgoogle);
}])
.directive('smartgooglemaps', function() {
return {
restrict:'E',
replace:false,
// transclude:true,
controller:'googleMapsCtr',
template: '<input id="google_places_ac" name="google_places_ac" type="text" class="input-block-level" ng-model="locationgoogle"/>',
link: function($scope, elm, attrs){
var autocomplete = new google.maps.places.Autocomplete($("#google_places_ac")[0], {});
}
}
})
I put my directive in the accordion directive which is included by :
<div ng-show="modeType =='CASH_ADVANCE'" static-include="submitter/expenseentry/cash-advance.html"></div>
what should I do to make my directive work?
Related
I'm consuming dynamically generated HTML from an API which may contain hyperlinks, and I'm wanting to replace the hrefs within them with ngClicks. The following directive appears to modify the HTML as intended when I check it in a DOM inspector, but clicking it does nothing. What am I doing wrong?
app.directive('replaceLinks', ['$compile', function ($compile) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
scope.$watch(function(scope) {
return scope.$eval(attrs.replaceLinks);
}, function(value) {
element.html(value);
angular.forEach(element.contents().find("a"), function(link) {
link.removeAttribute("href");
link.removeAttribute("target");
link.setAttribute("ng-click", "alert('test')");
});
$compile(element.contents())(scope);
});
}
};
}]);
Instead of removing the href please set it to blank (this will preserve the link css), also the ng-click calling the alert can be done by calling the alert('test') inside of a scope method, why the alert didn't fire, is explained in this SO Answer, please refer the below sample code!
// <body ng-app='myApp' binds to the app being created below.
var app = angular.module('myApp', []);
app.directive('replaceLinks', ['$compile', function($compile) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
angular.forEach(element.find("a"), function(link) {
link.setAttribute("href", "");
link.removeAttribute("target");
link.setAttribute("ng-click", "scopeAlert('test')");
});
$compile(element.contents())(scope);
}
};
}]);
// Register MyController object to this app
app.controller('MyController', ['$scope', MyController]);
// We define a simple controller constructor.
function MyController($scope) {
// On controller load, assign 'World' to the "name" model
// in <input type="text" ng-model="name"></input>
$scope.name = 'World';
$scope.scopeAlert = function(name) {
window.alert(name);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller='MyController' ng-app="myApp">
<div replace-links>
test 1
test 2
test 3
</div>
</div>
I'm trying to use popover for multiple instances using one controller and directive. The problem I'm running into is trying define an isolated scope for use in managing the content and state of the popover.
The issue is, I click to open the popover for 'My Content 01' and both popovers are opening up and both show the content from the second popover (My Content 02). Trying to get both to use their own scope and not the shared scope.
Here's my html markup:
<a class="helpful-tip"
data-my-popover
data-popover-label=""
data-uib-popover-template="dynamicPopover.templateUrl"
data-content="<p>My Content 01</p>"
data-popover-is-open="popoverState"
data-popover-trigger="outsideClick"
data-popover-placement="bottom">
<a class="helpful-tip"
data-my-popover
data-popover-label=""
data-uib-popover-template="dynamicPopover.templateUrl"
data-content="<p>My Content 02</p>"
data-popover-is-open="popoverState"
data-popover-trigger="outsideClick"
data-popover-placement="bottom">
Here's my controller:
angular.module('project.components.common.directives.myPopover', [
'ui.bootstrap'
])
.controller('myPopoverCtrl', function($scope, $rootScope) {
$scope.dynamicPopover = {
template: '<button type='button'
id='close'
class='close'
data-ng-show="true"
data-ng-click='tt_popoverState=false'> × </button><br>
<span data-ng-bind-html="htmlContent"></span>'
};
})
.directive('myPopover', function ($sce, $compile) {
return {
restrict: 'A',
template: '<span>{{ label }}</span>',
transclude: true,
controller: 'myPopoverCtrl',
link : function ($scope, element, attrs, ctrl, transclude) {
$scope.popoverState = false;
$scope.label = attrs.popoverLabel;
$scope.htmlContent = $sce.trustAsHtml(attrs.content);
element.append(transclude());
console.log(attrs);
}
};
});
https://angular-ui.github.io/bootstrap/ -> Popover
https://github.com/angular-ui/bootstrap/tree/master/src/popover
take a look at the following code:
html:
<body ng-app="myApp">
<div ng-controller="MainController">
<input type="button" ng-click="talk()" value="outside directive" />
<div my-element>
<input type="button" ng-click="talk()" value="inside directive" />
</div>
</div>
</body>
js:
var app = angular.module('myApp', []);
app.controller('MainController', function($scope){
$scope.talk = function() {
alert('HELLO1');
}
});
app.directive('myElement', function(){
return {
restrict: 'EA',
scope: {},
controller: function($scope) {
$scope.talk = function() {
alert('HELLO2');
}
}
};
});
as you can see, there's a controller, which nests a directive.
there are 2 buttons, one in controller level (outside of directive), and one is inside the directive my-element.
the main controller defines a scope method talk, the nested directive controller also defines a method - talk - but keep in mind that directive has isolated scope (i'd expect that talk method won't be inherited into directive's scope).
both buttons result an alert of 'HELLO 1', while i expected the second button (inside directive) to alert 'HELLO 2' as defined in directive controller, but it doesn't - WHY?
what am i missing here? how could i get a result when the second button will alert 'HELLO 2' but with the same method name ("talk") ?
thanks all
If you want the inner content to use the directive scope, you need to use manual transclusion:
app.directive('myElement', function(){
return {
restrict: 'EA',
scope: {},
transclude: true,
link: function(scope, element, attr, ctrl, transclude) {
transclude(scope, function(clone, scope) {
element.append(clone);
});
},
controller: function($scope) {
$scope.talk = function() {
alert('HELLO2');
}
}
};
});
By default, transcluded content uses a sibling of the directive scope. I actually don't know how angular handles DOM content for directives that don't use transclude (which is what makes this an interesting question), but I would assume from the behavior you are seeing that those elements use the directive's parent scope by default.
This will work for you
<body ng-app="myApp">
<div ng-controller="MainController">
<input type="button" ng-click="talk()" value="outside directive" />
<div my-element></div>
</div>
</body>
app.directive('myElement', function(){
return {
restrict: 'A',
template: '<input type="button" ng-click="talk()" value="inside directive">',
replace: true,
scope: {},
controller: function($scope) {
$scope.talk = function() {
alert('HELLO2');
}
}
};
});
I have a directive that links to a textbox on the form, and I would like for this directive to set the 'required' error.
Here's a fiddle that shows what I'm trying to do
http://jsfiddle.net/scottieslg/7qLsj3rr/3/
Html:
<div ng-app='myApp' ng-controller='TestCtrl'>
<ng-form name='testForm'>
<input type='text' name='myInput' />
<div ng-messages="testForm.myInput.$error">
<div ng-message="required">Required</div>
</div>
<test-directive ng-model='testModel'></test-directive>
</ng-form>
</div>
Javascript:
var app = angular.module('myApp', ['ngMessages']);
app.controller('TestCtrl', function($scope) {
$scope.testModel = {}
});
app.directive('testDirective', function() {
return {
restrict: 'E',
require: 'ngModel',
template: '<div><button ng-click="setError()">Set Error</button></div>',
link: function(scope, element, attrs, ngModelCtrl) {
scope.setError = function() {
// How can I set .setValidate('require', true) on myInput from here??
}
}
}
});
If you want the test-directive to be able to control the ngModelController instance on a separate named input in a form, then using the ng-model directive again isn't the right thing to do, as that would create a new ngModelController instance on test-directive.
What the test-directive actually needs to know is the name of the input which has the controller:
<test-directive name='myInput'></test-directive>
Then it can access the form controller, using
require: '^form',
and use the name attribute value to find the ngModelController instance on the form:
link: function(scope, element, attrs, formController) {
scope.setError = function() {
var ngModelCtrl = formController[attrs.name];
ngModelCtrl.$setValidity('required', false);
}
}
You can see this at http://jsfiddle.net/7qLsj3rr/6/ .
Note: if you're using required as the key, then as soon as you type in the input again again, angular's own required validation will kick in an remove the error.
I am attempting to access the form inside my directive for validation purposes, so I'd like access to $setPristine, however, I can't seem to figure out how to get the form if it's created using a templateUrl.
I have a plunker detailing the issue here: http://plnkr.co/edit/Sp53xzdTbYxL6DAue1uV?p=preview
I'm getting an error:
Controller 'form', required by directive 'testDirective', can't be found!
Here is the relevant Plunker code:
.js:
var app = angular.module("myApp", []);
app.directive("testDirective", function() {
return {
restrict: 'E',
scope: {},
templateUrl: "formTemplate.html",
require: "^form", // <-- doesn't work
link: function (scope, element, attrs, ctrl) {
console.log(ctrl);
scope.open = function() {
// Would like to have access to the form here
// ctrl.$setPristine();
}
},
controller: function($scope) {
$scope.firstName = "Mark";
$scope.save = function(form) {
console.log(form);
}
}
}
})
formTemplate.html:
<form name="testForm" ng-click="save(testForm)">
<input type="text" ng-model="firstName" />
<br>
<input type="submit" value="Save" />
</form>
How can I attach the form in formTemplate.html to the isolated scope of my directive?
http://plnkr.co/edit/41hhRPKoIsZ9C8Y9Yi87?p=preview
Try this in your directive:
var form1 = element.find('form').eq(0);
formCtrl = form1.controller('form');
console.log(formCtrl);
this should grab the controller for the form.