I need to add an attribute to a custom angular directive but I do not know how to bind the attribute (width) from the html part to the javascript that manages the behavior.
this is the html:
<div class="dropdown btn-group">
<button type="button" class="btn btn-default" data-bind="dropdown-label">{{initialValue}}</button>
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu dropdown-menu-scrollable" role="menu" aria-labelledby="dropdownMenu">
<li role="presentation" ng-repeat="value in values"
ng-click="clickHandler(value,$event)">
<a role="menuitem" tabindex="-1">{{value}}</a>
</li>
</ul>
this is the javascript behind html:
angular.module('platform.directives').directive('dropdownComponent', function() {
'use strict';
return {
restrict: 'E',
scope: {
initialValue: '#',
values: '=',
selectedValue: '='
},
templateUrl: 'modules/directives/dropdown/dropdown.html',
link: function(scope) {
scope.clickHandler = function findAndFillSelectedValueAndCloseDropDownArea(value, event) {
var $target = $(event.currentTarget);
$target.closest('.btn-group')
.find('[data-bind="dropdown-label"]').text($target.text())
.end()
.children('.dropdown-toggle').dropdown('toggle');
scope.selectedValue = value;
return false;
};
}
};
});
this is a usage:
<dropdownComponent
initial-value={{'PERMISSION.CREATE.DROPDOWN.RESOURCE'|translate}}
selected-value="permissionCtrl.permission.resourceId"
values="permissionCtrl.resources"
width="200px">
</dropdownComponent>
So basically I want to add a width attribute to this angular directive.
Thank you for your help!
You just need to pass it to the scope like you do with all 3 other variables:
scope: {
initialValue: '#',
values: '=',
selectedValue: '=',
width: "#"
},
And now you can just use scope.width in the javascript of the directive to add to elements for example.
And in HTML (which you should change dropdownComponent to dropdown-component by the way):
<dropdown-component
initial-value={{'PERMISSION.CREATE.DROPDOWN.RESOURCE'|translate}}
selected-value="permissionCtrl.permission.resourceId"
values="permissionCtrl.resources"
width="200px"></dropdown-component>
EDIT: In your directive HTML, change the first button to:
<button type="button"
class="btn btn-default"
data-bind="dropdown-label"
ng-style="width: {{width}}">{{initialValue}}</button>
Related
This question already has answers here:
How to call a method defined in an AngularJS directive?
(13 answers)
Closed 4 years ago.
Someome, please tell me how can I access a javascript directive link function from a typedScript controller. I have a button outside the directive and I want to call that function in my pageController when my user button is clicked. I´ve tried several tutorials but i can´t have it working.
1-This is an extract of th directive.js file
I want to call the function from my controller
directive.js - javascript
(function () {
'use strict';
angular.module('pdf', []).directive('ngPdf', ['$window', function ($window) {
return {
restrict: 'E',
templateUrl: function (element, attr) {
return attr.templateUrl ? attr.templateUrl : 'app/_infrastructure/pdfViewer/viewer.html';
},
scope: {
pdfUrl: '='
},
link: function (scope, element, attrs) {
var url = scope.pdfUrl;
scope.goPrevious = function () {
if (scope.pageToDisplay <= 1) {
return;
}
scope.pageToDisplay = parseInt(scope.pageToDisplay) - 1;
scope.pageNum = scope.pageToDisplay;
};
}
};
}]);
})();
2-This is the directive template (.hmtl)
<nav class="text-center">
<div class="prev-next-button previous">
<button class="btn btn-danger btn-sm" ng-click="goPrevious()">
<i class="fa fa-arrow-left fa-lg"></i>
</button>
</div>
<div class="prev-next-button next">
<button class="btn btn-danger btn-sm" ng-click="goNext()">
<i class="fa fa-arrow-right fa-lg"></i>
</button>
</div>
<span>Pág: </span>
<input type="text" class="searchPageNumber" min="1" ng-model="pageNum">/
<span>{{pageCount}}</span>
<button class="btn btn-danger btn-sm" title="Diminuir" ng-click="zoomOut()">
<i class="fa fa-minus"></i>
</button>
<button class="btn btn-danger btn-sm" ng-click="fit()">
100%
</button>
<button class="btn btn-danger btn-sm" title="Aumentar" ng-click="zoomIn()">
<i class="fa fa-plus"></i>
</button>
</nav>
<hr style="border-top: 0px; margin-bottom: 0px!important;margin-top: 1px!important" />
<div style="max-height:900px;max-width:1051px;overflow: auto;">
<canvas id="pdf" style="border:2px solid #000000;"></canvas>
</div>
3- This the user page (.html)
<div class="main-content-inner" ng-controller="MyController as Ctrl">
<div class="col-xs-8" >
<div class="form-group" ng-show="(Ctrl.currentProcesso.estadoProcessoId==1 || Ctrl.currentProcesso.estadoProcessoId== 3 ||Ctrl.currentProcesso.estadoProcessoId==6) && Ctrl.appUserBasicInfo.role == 'Escrivão'">
<ng-pdf data-pdf-url="file.pdf" canvasid="pdf" scale="page-fit" page="1"></ng-pdf>
</div>
</div>
<div class="col-xs-3">
<button class="btn btn-success btn-sm btn-next"
ng-click="Ctrl.controllerMethodToCallDirectiveFunction()"
ng-show="true">
NEXT
<i class="tcicons-icon fa fa-arrow-right icon-on-right"></i>
</button>
</div>
</div>
4-Finally this is my controller (MyController.ts)
public enumerarProcessoPushPop = (): boolean => {
//I want to call the directive method here
return true;
}
Methods inside Angular directives are not meant to be called. From the Angularjs documentation:
At a high level, directives are markers on a DOM element (such as an attribute, element
name, comment or CSS class) that tell AngularJS's HTML compiler ($compile) to attach a specified behavior to that DOM element (e.g. via event listeners), or even to transform the DOM element and its children.
I'm trying list data according with data choose on a drop down menu.
My service list data with a hardcode (id 6).
var url = 'http://localhost:3854/listarServicosByEstab/' + '6'; // Hardcode!
How do I pass the select item ID to the service?
Dropdown HTML (ng-click doesnt work):
<!-- Combobox -->
<div class="row">
<div class="dropdown" ng-controller="EstabelecimentosPageCtrl">
<button class="btn btn-default dropdown-toggle" type="button" id="dropdown_estabelecimentos" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
Estabelecimentos
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdown_estabelecimentos" >
<li>
<a ng-repeat="estab in listaDeEstabelecimentos" href="#" ng-click="$parent.current = item">
{{estab.nomeEstab}}
</a>
</li>
</ul>
Choose Test: {{item}}
</div>
</div>
Menu Controller:
.controller('ListServicoCtrl', function($scope, $state, ListServicoService) {
ListServicoService.listarServicos().then(function(dados){
$scope.listaDeServicos = dados;
}); });
Service:
.service('ListServicoService', function($http){
var url = 'http://localhost:3854/listarServicosByEstab/' + '6'; // Hardcode!
return{
listarServicos : function (){
return $http.get(url).then(function(response){
return response.data;
});
}
}});
<div class="row">
<div class="dropdown" ng-controller="EstabelecimentosPageCtrl">
<button class="btn btn-default dropdown-toggle" type="button" id="dropdown_estabelecimentos" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
Estabelecimentos
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdown_estabelecimentos" >
<li>
<a ng-repeat="estab in listaDeEstabelecimentos" ng-click="passdata(estab.Id)">
{{estab.nomeEstab}}
</a>
</li>
</ul>
Choose Test: {{item}}
</div>
</div>
Your Controller
.controller('ListServicoCtrl', function($scope, $state, ListServicoService) {
$scope.passdata = function(id){
ListServicoService.listarServicos(id).then(function(dados){
$scope.listaDeServicos = dados;
});
} });
Your Service
.service('ListServicoService', function($http){
return{
listarServicos : function (id){
return $http.get('http://localhost:3854/listarServicosByEstab/' + id).then(function(response){
return response.data;
});
}
}});
Remove href from anchor tag and make a function like I have shown in controller. By assuming that your json contains value like Id I have demonstrated it. Hope this code will work for you.
I am trying to add custom directive in my app. But it is not getting called on button click event.
my controller-
appServices.directive('customClick', function() {
return {
restrict: 'E',
require: 'ngModel',
link: function($scope, element, attrs) {
$scope.deleteFieldMap = function() {
alert('inside click');
}
}
}
}
my jsp-
<button custom-click class="btn btn-danger btn-sm"
data-style="zoom-in"
ng-click="deleteFieldMap(editProductJob,$index)"
name="jobFileKey"
title="Delete" >
<span class="glyphicon glyphicon-remove"></span>
</button>
What i am doing wrong here?
Your directive is restricted to 'E'. Which means to "element".
You should change it to 'A' since you expect an it as an "attribute".
Check out the reference documentation :
https://docs.angularjs.org/guide/directive
Edit : As explained by Medet, you also miss the "ng-model" on your element. Remove the definition if is his unecessary or add the attribute if you really expect it.
Regards
First issue as noted above is element.restrict: 'A', seconds issue - you must have ng-model attribute on your button, demo below
angular.module('app', [])
.run(function($rootScope) {
$rootScope.test = '123qe';
}).directive('customClick', function() {
return {
restrict: 'A',
require: 'ngModel',
link: function($scope, element, attrs, ngModelCtrl) {
$scope.deleteFieldMap = function() {
alert('inside click' + ngModelCtrl.$viewValue);
}
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.js"></script>
<div ng-app="app">
<button custom-click ng-click="deleteFieldMap(editProductJob,$index)" ng-model="test">
remove
</button>
</div>
you should use your custom directive as follow:
<custom-click class="btn btn-danger btn-sm"
data-style="zoom-in"
ng-click="deleteFieldMap(editProductJob,$index)"
name="jobFileKey"
title="Delete" >
<span class="glyphicon glyphicon-remove"></span>
</custom-click>
as an element!
I have two separate angular directives that I'm calling (see below markup), but the last template is always the one that appears for both directives in the markup section below.
As you can see, I have the templateUrl set differently for both directives (in the directives section below), yet the last one in the markup section (attachment-modal.html) is always the one that appears.
If I make the download-modal.html the last one, then that template will appear for both directives. This is also seen by placing breakpoints in each of the directives. The first directive that you have defined in the markup, never gets executed even though it gets clicked on.
Both templates have different markup in them. If I comment out one of the directives, then the template associated with that directive comes out for both directives.
After manipulating the markup, no matter what I did, whichever directive was the latter one, is the directive that got executed.
It seems like I can't have two directives on the same web page because only the last one defined in the markup will get executed.
I tried it in both IE & Chrome.
What do I need to do to have the associated templates come out for each of the respective directives?
markup
<h3 class="panel-title">Check Deposit Header Information <download download-type="CK" download-id={{cdmCtrl.copiedRow.CheckDepositHeaderId}}>
</download> <attachment attachment-type="CK" attachment-id={{cdmCtrl.copiedRow.CheckDepositHeaderId}}>
</attachment>
</h3>
templates
download template
<p>For Testing Purpose: Download Type: {{downloadCtrl.attributes.downloadType}}</p>
<p>For Testing Purpose: ID: {{downloadCtrl.attributes.downloadId}}</p>
<div class="modal-header">
<h3 class="modal-title">File Download</h3>
</div>
<div class="modal-footer">
<div class="btn-toolbar pull-right" role="toolbar">
<div class="btn-group" role="group" >
<button type="button" class="btn btn-default" file-download download-type={{downloadCtrl.attributes.downloadType}} download-id={{downloadCtrl.attributes.downloadId}}>Download files</button>
</div>
<div class="btn-group" role="group">
<button type="button" class="btn btn-default" ng-click="$close()">Close</button>
</div>
</div>
</div>
upload template
<p>For Testing Purpose: Attachment Type: {{attachCtrl.attributes.attachmentType}}</p>
<p>For Testing Purpose: ID: {{attachCtrl.attributes.attachmentId}}</p>
<div class="modal-header">
<h3 class="modal-title">File Attachment</h3>
</div>
<div class="modal-body">
<input type="file" id="inpFile" file-model="myFile" />
</div>
<div class="modal-footer">
<div class="btn-toolbar pull-right" role="toolbar">
<div class="btn-group" role="group" >
<button type="button" class="btn btn-default" file-upload attachment-type={{attachCtrl.attributes.attachmentType}} attachment-id={{attachCtrl.attributes.attachmentId}}>Upload</button>
</div>
<div class="btn-group" role="group">
<button type="button" class="btn btn-default" ng-click="$close()">Close</button>
</div>
</div>
</div>
directives
.directive('attachment', ['$modal', function($modal) {
return {
restrict: 'E',
transclude: false,
replace: true,
template: '<a style="padding-right: 5px" class="pull-right" href="#" ng-click="open()"><i class="fa fa-files-o fa-lg" style="padding-right: 5px"></i>Attachment</a>',
link: function(scope, elem, attrs, controller) {
scope.open = function() {
$modal.open({
templateUrl: root + 'AccountingModule/modal/attachment/attachment-modal.html',
size: 'md',
backdrop: true,
controller: ['attributes', function(attributes) {
var viewModel = this;
viewModel.attributes = attributes;
}],
controllerAs: 'attachCtrl',
resolve: {
attributes: function() {
return attrs;
}
}
});
}
}
}
}])
.directive('download', ['$modal', function($modal) {
return {
restrict: 'E',
transclude: false,
replace: true,
template: '<a style="padding-right: 5px" class="pull-right" href="#" ng-click="open()"><i class="fa fa-files-o fa-lg" style="padding-right: 5px"></i>Download</a>',
link: function(scope, elem, attrs, controller) {
scope.open = function() {
$modal.open({
templateUrl: root + 'AccountingModule/modal/attachment/download-modal.html',
size: 'md',
backdrop: true,
controller: ['attributes', function(attributes) {
var viewModel = this;
viewModel.attributes = attributes;
}],
controllerAs: 'downloadCtrl',
resolve: {
attributes: function() {
return attrs;
}
}
});
}
}
}
}])
For the ng-click events in the directives, I needed to specify a different name for each scope opened.
For instance, openattachments & opendownloads for the scope.open functions since scope was a global variable and the last one always overwrote the first one.
template: '<a style="padding-right: 5px" class="pull-right" href="#" ng-click="openattachments()"><i class="fa fa-files-o fa-lg" style="padding-right: 5px"></i>Attachment</a>',
I have template like this:
<span class="collapsibleBox">
<a ng-show="visible" ng-click="hide()" class="minus">
<i class="fa fa-minus-square-o"></i>
</a>
<a ng-show="!visible" ng-click="show()" class="plus">
<i class="fa fa-plus-square-o"></i>
</a>
<div ng-show="visible || preview" ng-class="preview ? 'previewBox' : 'contentBlock'" ng-bind-html="htmlContent"></div>
</span>
with css:
.api .previewBox {
height: 1.25em;
overflow: hidden;
}
And I need to not show plus and minus sign icons when div with class htmlContent is only one line, how can I do this in Angular.
I came up with this directive:
module.directive('oneLine', function($rootScope) {
return {
restrict: 'A',
scope: {
text: '=',
oneLine: '='
},
link: function($scope, $element, $attrs) {
angular.element(window).bind('resize', function() {
var height = $element.html('M').show().height();
$element.html($scope.text);
$scope.oneLine = height == $element.height();
$element.hide();
if (!$rootScope.$$phase) {
$rootScope.$apply(); // $scope throw "digest in progress" exception
}
}).trigger('resize');
}
};
});
and use it like this:
<span class="collapsibleBox">
<span ng-hide="hideButtons">
<a ng-show="visible" ng-click="hide()" class="minus">
<i class="fa fa-minus-square-o"></i>
</a>
<a ng-show="!visible" ng-click="show()" class="plus">
<i class="fa fa-plus-square-o"></i>
</a>
</span>
<div class="contentBlock" one-line="hideButtons" text="htmlContent"></div>
<div ng-show="visible || preview" ng-class="preview ? 'previewBox' : 'contentBlock'" ng-bind-html="htmlContent"></div>
</span>
You can set your CSS to only show one line, but show ellipses when the text overflows. You don't get +/- buttons, but it might be usable for you.
See http://www.w3schools.com/cssref/css3_pr_text-overflow.asp