I have created directive in Angular.I am calling popover directive from mybox. i wish to make popover directive Active only after click on Enable button .
I thought for ng-include but incase of directive how can i use ?
Please suggest ....
Fiddle :: http://jsfiddle.net/JNqqU/278/
Directive Code ::
var bootstrap = angular.module("bootstrap", []);
bootstrap.directive('myBox', function ($compile) {
return {
restrict: "E",
transclude: true,
template: "<span>Hello In side Box <a href='#' pop-over items='items' title='Mode of transport'>Show Pop over</a> </span>",
link: function (scope, element, attrs) {
var popOverContent;
if (scope.items) {
var html = getTemplate("items");
popOverContent = $compile(html)(scope);
}
var options = {
content: popOverContent,
placement: "bottom",
html: true,
title: scope.title
};
$(element).popover(options);
},
scope: {
items: '=',
title: '#'
}
};
});
bootstrap.directive('popOver', function ($compile) {
var itemsTemplate = "<ul class='unstyled'><li ng-repeat='item in [1,2,3,4,5,6,7,8]'>{{item}}</li></ul>";
var getTemplate = function (contentType) {
var template = '';
switch (contentType) {
case 'items':
template = itemsTemplate;
break;
}
return template;
}
return {
restrict: "A",
transclude: true,
template: "<span ng-transclude></span>",
link: function (scope, element, attrs) {
var popOverContent;
if (scope.items) {
var html = getTemplate("items");
popOverContent = $compile(html)(scope);
}
var options = {
content: popOverContent,
placement: "bottom",
html: true,
title: scope.title
};
$(element).popover(options);
},
scope: {
items: '=',
title: '#'
}
};
});
bootstrap.directive( 'dismissPopovers', [ '$http', '$templateCache', '$compile', '$parse', function ( $http, $templateCache, $compile, $parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.bind('mouseup', function(e) {
var clickedOutside = true;
$('.popover-link').each(function() {
if ($(this).is(e.target) || $(this).has(e.target).length) {
clickedOutside = false;
return false;
}
});
if ($('.popover').has(e.target).length) {
clickedOutside = false;
}
if (clickedOutside) {
$('.popover').prev().click();
}
});
}
};
}]);
You could override the bootstrap directive to pass it a parameter wether it should display the popver or not. First add a variable to the directive attributes :
Controller :
$scope.popOverShouldOpen = whatYouWantThere;
Template :
<div pop-over pop-over-should-open="popOverShouldOpen"></div>
Then add it to the directive scope :
scope: {
items: '=',
title: '#',
popOverShouldOpen: "="
}
Then put "if" statements inside the link function :
link: function (scope, element, attrs) {
if( scope.popOverShouldOpen === true ){
var popOverContent;
if (scope.items) {
var html = getTemplate("items");
popOverContent = $compile(html)(scope);
}
var options = {
content: popOverContent,
placement: "bottom",
html: true,
title: scope.title
};
$(element).popover(options);
}
},
Or you could simply do this, depending on your context :
<div pop-over ng-show="popOverShouldOpen"> Hello there ! </div>
<div ng-hide="popOverShouldOpen"> Hello there ! </div>
Of course this last one is a quick hack. For a massive usage prefer the first !
Related
environment
AnuglarJS 1.6x
ui-bootstrap2.5
I want to display error messages with tool tip on validation with AngularJS.
I am referring to the directive created by the following jQuery and bootstrap.js with reference to it,
How can I implement it with ui - bootstrap?
Reference sample
http://jsfiddle.net/y9ujn/5/
How to show form input errors using AngularJS UI Bootstrap tooltip?
I tried trying to add attributes of ui-tooltip at the place where tooltip was set in Query, but it does not work.
<script>
var app = angular.module("app", ['ui.bootstrap']);
app.controller('Ctrl', function ($scope) {});
app.directive('validationMessage', function () {
return {
restrict: 'A',
priority: 1000,
require: '^validationTooltip',
link: function (scope, element, attr, ctrl) {
ctrl.$addExpression(attr.ngIf || true);
}
}
});
app.directive('validationTooltip', function ($timeout) {
return {
restrict: 'E',
transclude: true,
require: '^form',
scope: {},
template: '<span class="label label-danger span1" ng-show="errorCount > 0">hover to show err</span>',
controller: function ($scope) {
var expressions = [];
$scope.errorCount = 0;
this.$addExpression = function (expr) {
expressions.push(expr);
}
$scope.$watch(function () {
var count = 0;
angular.forEach(expressions, function (expr) {
if ($scope.$eval(expr)) {
++count;
}
});
return count;
}, function (newVal) {
$scope.errorCount = newVal;
});
},
link: function (scope, element, attr, formController, transcludeFn) {
scope.$form = formController;
transcludeFn(scope, function (clone) {
/
var badge = element[0].firstChild;
var tooltip = angular.element('<div class="validationMessageTemplate tooltip-danger" />');
tooltip.append(clone);
element.append(tooltip);
$timeout(function () {
scope.$field = formController[attr.target];
badge.attr( 'uib-tooltip', "test")
});
});
}
}
});
I've lost my bearings with regards to why I can't pass updates to my directives.
What I'm trying to accomplish with the following piece of code is to be able to set focus on by pressing a button. The problem is however that the "focus" binding on drInput only ever is set when the directive have loaded when it should change whenever it changes in drWrap. How come and how do I get around this?
And now, ladies and gentlemen, I present to you: THE CODE!
<div ng-app="myApp">
<dr-wrap></dr-wrap>
</div>
var myApp = angular.module('myApp', []);
myApp.directive('drWrap', function($timeout) {
return {
scope: {
focus: '=?bind'
},
restrict: 'E',
replace: 'true',
template: '<div><button ng-click="openSearch()">focus</button><dr-input focus="focusSearch" /></div>',
link: function(scope, elem, attr){
scope.openSearch = function(){
$timeout(function(){
scope.focusSearch = true
alert('scope.focusSearch 2 = ' + scope.focusSearch)
}, 1000)
}
}
};
})
.directive('drInput', function() {
return {
scope: {
focus: '=?bind'
},
restrict: 'E',
replace: 'true',
template: '<input type="test" focus-me="{{ focus }}" />',
link: function(scope, elem, attr){
scope.$watch('focus', function(value){
if(value != undefined){
scope.focus = value
alert('scope.focus = ' + scope.focus)
}
})
}
};
})
.directive('focusMe', ['$timeout', function ($timeout) {
return {
link: function (scope, element, attrs) {
attrs.$observe('focusMe', function(value){
if ((value === true) || (value == 'true')) {
$timeout(function () {
element[0].focus()
scroll(element[0])
})
} else {
element[0].blur()
}
})
}
}
}])
And the FIDDLE!
https://jsfiddle.net/L56rdqLp/168/
When you write scope: { focus: '=?bind' }, this means that the attribute name should be bind but not focus, so the template of drWrap should look like:
template: '<div><button ng-click="openSearch()">focus</button><dr-input bind="focusSearch" /></div>'
Add ngBlur event handler to drInput directives input like:
template: '<input type="test" focus-me="{{ focus }}" ng-blur="focus = false"/>',
to change the model to false, when input has lost its focus.
Here is working fiddle.
I have a directive called tabset
angular.module('widgets')
.directive('tabset', function() {
return {
restrict: 'E',
transclude: true,
scope: {},
controllerAs: 'tabs',
bindToController: {
tabInfo: '=tabdata'
},
templateUrl: 'Template.html',
link: function(scope, element, attrs, tabs) {
//var tabs = this;
scope.$watch('tabs.tabInfo', function() {
tabs.populateDataProvider();
console.log('this just kicked');
}, true);
},
controller: ['$filter', '$state', function($filter, $state) {
this.activeIndex = this.activeIndex < 0 ? 0 : this.activeIndex;
this.selectTab = function selectTab(tab) {
$state.go(tab.state);
};
}]
};
});
I now have a dependent directive called checkTab which requires "tabset" and on change to tabset.tabInfo, teh watch needs to kick in and populatedataprovider needs to be triggered. However that does not seem to be teh case.
Here is the checkTab directive,
angular.module('widgets')
.directive('checkTab', ['XXXService',
function(XXXService) {
return {
restrict: 'A',
require: 'tabset',
link: function(scope, element, attrs, ctrls) {
var tabCtrl = ctrls;
tabCtrl.tabInfo.push({
name: 'newtab',
state: 'newtab'
});
**var selectFn = tabCtrl.populateDataProvider;**
tabCtrl.populateDataProvider = function() {
selectFn.apply(tabCtrl, arguments);
(function recurse(dataObj) {
for (var key in dataObj) {
var obj = dataObj[key];
if (obj.hasOwnProperty('children')) {
for (var i = 0; i < obj.children.length; i++) {
recurse(obj.children[i]);
}
}
}
})(tabCtrl.dataprovider);
};
}
};
}
]);
However , when the new tab is added to tabset.tabInfo. I get an error Cannot read property 'apply' of undefined where teh selectFn is undefined.
I am opening a dialog-box on click of button.I want to add endless scroll in that.
Problem:
When user scrolls at the end of dialog-box i want to call addMoreData() written in controller.
HTML of Dialog-box:
<modal-dialog show='modalShown' width='60%' height='325px' >
<div id='diaogContainer'>
<p>Modal Content Goes here<p>
</div>
</modal-dialog>
Controller:
sampleApp.controller('view3Controller', function($scope) {
$scope.modalShown = false;
$scope.toggleModal = function() {
$scope.modalShown = !$scope.modalShown;
}
**$scope.showMore = function(){
console.log('showMore');
}**
});
Directive of Dialog-box:
sampleApp.directive('modalDialog', function() {
return {
restrict: 'E',
scope: {
show: '='
},
replace: true, // Replace with the template below
transclude: true,
link: function(scope, element, attrs) {
scope.dialogStyle = {};
if (attrs.width)
scope.dialogStyle.width = attrs.width;
if (attrs.height)
scope.dialogStyle.height = attrs.height;
scope.hideModal = function() {
scope.show = false;
};
},
template: "<div class='ng-modal' ng-show='show'><div class='ng-modal-overlay'ng-click='hideModal()'></div><div class='ng-modal-dialog' hello **scrolly='showMore()'** ng-style='dialogStyle'><div class='ng-modal-close' ng-click='hideModal()'>X</div><div class='ng-modal-dialog-content' ng-transclude></div></div></div>"
};
});
Directive to load more data:
sampleApp.directive('hello', function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var raw = element[0];
element.bind('scroll', function () {
console.log(raw.scrollTop +'-------'+raw.offsetHeight+'----'+raw.scrollHeight);
if (raw.scrollTop + raw.offsetHeight >= raw.scrollHeight) {
// here is problem
// I am not able to call function through this attr
//
**scope.$apply(attrs.scrolly);**
}
});
}
};
});
You can't pass in a function to a directive through an attribute, you can however pass it through an isolate scope. Pass a reference to the function you wish to call to the directive:
sampleApp.directive('hello', function () {
return {
restrict: 'A',
scope:{
onScrollEnd:'&'
},
link: function (scope, element, attrs) {
var raw = element[0];
element.bind('scroll', function () {
console.log(raw.scrollTop +'-------'+raw.offsetHeight+'----'+raw.scrollHeight);
if (raw.scrollTop + raw.offsetHeight >= raw.scrollHeight) {
scope.onScrollEnd();
}
});
}
};
});
Now assuming you have the addMoreData() function defined on your controller, you can pass it to the directive this this:
<div hello on-scroll-end='addMoreData()'></div>
EDIT
I think the problem is that the hello directive can't access functions on the parent controller since the modalDialog directive is using an isolated scope, therefore making everything o the parent controller invisible. Pass the function to through the isolate scope of the modalDialog Directive as well:
scope: {
show: '=',
onScrollEnd:'&'
},
you can try like this.
Directive part
var module = angular.module('direc');
module.directive("direcApp", ['$timeout', function ($timeout) {
return {
restrict: 'E',
templateUrl: "template/template.html",
compile: function (iel, iattr) {
return function (scope, el, attr) {
}
},
scope: {
type: "#",
items: '=',
onClick: '&',
val: "="
},
controller: function ($scope) {
$scope.selectItem = function (selectedItem) {
$scope.val = selectedItem;
if (angular.isFunction($scope.onClick)) {
$timeout($scope.onClick, 0);
}
};
}
};
}]);
Controler part
var app = angular.module('app', ['direc']);
app.controller("appCtrl", ['$scope', '$http', function ($scope, $http) {
var t = {
count: function () {
return $scope.$$watchersCount; // in angular version 4 get total page listener
},
val1: "",
onClick: function () {
console.log($scope.data.val1);
},
items: [{ text: 'Seçenek 1', value: '1' },
{ text: 'Seçenek 2', value: '2' },
{ text: 'Seçenek 3', value: '3' },
{ text: 'Seçenek 4', value: '4' },
{ text: 'Seçenek 5', value: '5' }]
};
angular.extend(this, t);
}]);
Html part
<div ng-controller="appCtrl as data">
<div><b>Watcher Count : {{data.count()}}</b></div>
<direc-app items="data.items"
val="data.val1"
on-click="data.onClick1()"
>
</selection-group>
</div>
Add data as parameter to directive: scope: { data: '='}, and in directive just data.push({name:'i am new object'})
Add function parameter to directive as suggested in previous answer.
I am created tooltip directive. but data comes from api , so on page load directive initializes and then data is loaded through api.api data comes later hence directive is not initialized properly .
how can i handle this ?
HTML::
<strong href="#" pop-over items="result" title="detailes" display-length="5">{[{ result.name}]}
Javascript :
listingApp.directive('popOver', function ($compile) {
var itemsTemplate = "<ul class='unstyled'><li>{{items}}</li></ul>";
var getTemplate = function (contentType) {
var template = '';
switch (contentType) {
case 'items':
template = itemsTemplate;
break;
}
return template;
}
return {
restrict: "A",
transclude: true,
scope: {
items: '=',
title: '#',
//popContent: '=',
displayLength:'#'
},
transclude: true,
template: "<span ng-transclude></span>",
link: function (scope, element, attrs) {
debugger;
// console.log('^^^^^^^^^^^^^^^'+attrs.popContent);
var popOverContent;
if (scope.items) {
var html = getTemplate("items");
popOverContent = $compile(html)(scope);
}
var options = {
content: popOverContent,
placement: "bottom",
html: true,
title: scope.title,
trigger: "hover"
};
if ((scope.items || '').length > attrs.displayLength) {
$(element).find('.display_data').text(scope.items.substring(0, attrs.displayLength));
element.attr('title', scope.items);
$(element).find('.view_more').popover(options);
} else {
$(element).find('.display_data').text(scope.items);
}
}
};
});
try wrapping your .popover plugin with a $timeout:
$timeout(function() {
$(element).find('.view_more').popover(options);
});