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
Related
In my directive I have a html button. I want to call a function when it is clicked. I have not much knowledge about angular js. So I want to open a modal when the button clicked.
I think the path is,
html button -> showModal() function inside the directive. this showModal() is a webservice function which call a modal with webservice.
I have added the ng-click="documentManagerButtonCtrl.showDocumentModal()" in the html.
but it is not calling the directive function. can anyone explain how to open a modal with a service when click the button
<div class="col">
<a class='btn'
ng-click="pimDocumentManagerButtonCtrl.showDocumentModal()"
data-target='demoModal' modal>Create</a>
</div>
(function () {
'use strict';
angular
.module('app.directives')
.directive('documentManagerButton', documentManagerButton);
/* #ngInject */
function documentManagerButton() {
return {
restrict: 'E',
templateUrl: 'directives/document_manager.html',
scope: {
datagroupName: "#",
employeeNumber: "=",
documentTemplateDetails: "=",
employeeService: "="
},
bindToController: true,
link: function (scope, element, attrs) {
},
controller: documentManagerController,
controllerAs: 'DocumentManagerButtonCtrl'
};
}
documentManagerController.$inject = ['webservice', '$q', 'modalHelperService'];
function documentManagerController(webservice, $q) {
var vm = this;
function showDocumentModal(){
modalHelperService.showModal(
'app/document/document_modal.html',
'documentController',
'modal'
);
}
}
})();
Change
controllerAs: 'DocumentManagerButtonCtrl'
to
controllerAs: 'vm'
because you have
var vm = this;
After that you need expose showDocumentModal() function with
vm.showDocumentModal = showDocumentModal;
And then you can call with ng-click:
ng-click="vm.showDocumentModal()"
In this plunk I have an Angular UI modal with an alert popup that should display the modal height. Instead, it shows an empty variable. Where's the error?
HTML
<div the-modal></div>
Javascript
var app = angular.module("app", ['ui.bootstrap']);
app.controller("ctl", function($scope, $compile) {});
app.directive("theModal", function($uibModal, $timeout) {
return {
restrict: "AE",
scope: true,
link: function(scope, element, attrs, ctrl, transclude) {
scope.instance = $uibModal.open({
animation: false,
scope: scope,
template: 'Some Text',
appendTo: element
});
$timeout(function(){
alert("Modal height is: " + element.css("height"));
},500);
}
}
});
The content has been placed inside div with modal-dialog class inside directive modal placeholder element. So ideally you should be looking at element's inner modal-content class.
element[0].querySelector('.modal-dialog').offsetHeight
I am trying to change "Collapse" text to "Expand" on click of h2 tag. at the same time I am applying "active" class to h2 tag. using following directive, which is working fine, but now I am clueless about how to change "collapse" text to Expand on h2 tag click
HTML
<h2 class="panel-title" toggleclass>My Tandem URL</h2>
<a class="collapse-arrow">Collapse</a>
js
.directive("toggleclass", function () {
return {
restrict: 'A',
scope: false,
link: function (scope, element, attrs) {
element.bind("click", function () {
element.toggleClass('active');
});
}
}
})
Can anyone plz help..
The
If you want to do DOM manipulation in your directive you could change the contents of the element by doing:
var link = element.find('a');
link.text(link.text() === 'Collapse' ? 'Expand' : 'Collapse')`.
Using html instead of text also works.
You have to move the link inside the h2 to have the directive see the link.
Another approach is having the link text changed via the scope, but then you need to have a template and bind the link text to the directive scope. Then you have to wrap both elements in a directive.
This may make the solution a bit too big for this simple use case...
Another suggestion on making up an directive: encapsulates html and behaivor inside: fiddle .
angular.module('myModule', [])
.directive('togglable', function () {
return {
restrict: 'EA',
template: '<div><h2 class="panel-title" ng-class="{ active: isCollapsed }" ng-click="toggle()" ng-transclude></h2><a class="collapse-arrow">{{ isCollapsed ? "Expand" : "Collapse"}}</a></div>',
transclude: true,
replace: true,
scope: false,
controller: function ($scope) {
$scope.isCollapsed = false;
$scope.toggle = function () {
$scope.isCollapsed = !$scope.isCollapsed;
};
}
};
});
Key features:
- no manual DOM manipulaton;
- uses transclude feature;
Such a directive is easy to use:
<togglable>My Tandem URL</togglable>
Depending on how your app works, maybe you can try this:
HTML:
<h2 class="panel-title" ng-class="{'active': expand}" toggleclass>My Tandem URL</h2>
<a class="collapse-arrow" ng-hide="expand">Collapse</a>
<a class="collapse-arrow" ng-show="expand">Expand</a>
JS:
angular.module('myApp', [])
.controller('myCTRL', function($scope) {
$scope.expand = false;
})
.directive("toggleclass", function () {
return {
restrict: 'A',
scope: false,
link: function (scope, element, attrs) {
element.bind('click', function() {
scope.$apply(function() {
scope.expand = !scope.expand;
});
});
}
}
});
http://jsfiddle.net/uqbc9asf/
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?
In this example, I have two AngularJS KendoDatePickers. The first one works perfectly, if you click on the button you open the calendar. The second one is within a directive that has the transclude attribute set to true. If you click on the second button, you get an error.
My understanding is that the scope of the transcluded portion inherits from the control scope, so this should work. Where am I wrong?
This is the plunk
HTML
<input kendo-date-picker="picker" />
<button ng-click="openPicker()">Open Date Picker</button>
<my-window>
<input kendo-date-picker="picker2" />
<button ng-click="openPicker2()">Open Date Picker 2</button>
</my-window>
Javascript
var app = angular.module("app", [ "kendo.directives" ]);
app.controller('MyCtrl', function($scope) {
$scope.openPicker = function () {
$scope.picker.open();
};
$scope.openPicker2 = function () {
$scope.picker2.open();
};
});
app.directive('myWindow', function() {
return {
transclude: true,
scope: {
someVar: '='
},
restrict: 'EA',
template: function(element, attrs) {
var html = '<div ng-transclude></div>';
return html;
}
};
});
There are two things about your code:
first: you create an isolatedScope so you do not have access to the controller scope inside the directive scope.
second: transcluded content get their own scope. One way to work around this is by not using transclude at all, like the example below:
return {
transclude: false,
restrict: 'EA',
template: function(element, attrs) {
var html = '<div>'+element.html()+'</div>';
return html;
}
or use the link function and manually transclude the element with the scope of the directive