Directive contains transculde with isolated scope - angularjs

I have a template as following header, body(ng-transclude), footer
<div class="wfm-modal">
<div class="modal-header">
<button type="button" id="close-button" class="close" ng-click="cancel()" aria-label="Close"
ng-show="allowClose">
</button>
<h3 class="modal-title">{{title}}</h3>
</div>
<ng-transclude></ng-transclude>
<div class="modal-footer">
<div class="button-row text-right">
<!-- Save button -->
<button id="save" type="submit" ng-click="save()" class="btn btn-primary">
<span ng-if="saveLabel">
{{saveLabel}}
</span>
</button>
</div>
</div>
</div>
As you can see I have a wfm-modal which contains header body(which is ng-transclude) and footer.
My directive:
app
.directive('wfmModal', function ($window, $timeout, _, $log, $compile, $templateCache) {
'use strict';
var link = function (scope, element, attr, controller, transclude) {
transclude(scope.$parent, function(clone, scope) {
element.empty();
element.append(clone);
});
};
return {
restrict: 'E',
link: link,
templateUrl: 'directives/wfmModal/wfmModal.tpl.html',
replace: true,
transclude: true,
scope: {
title: '=',
allowClose: '=',
cancel: '=',
save: '=',
saveLabel: '#',
delete: '='
//delete: '=',
//deletePopover: '#'
}
};
})
My problem: when I dont add the
transclude(scope.$parent, function(clone, scope) {
element.empty();
element.append(clone);
});
to link function then the scope of the body(the content of ng-transclude) is empty on the save that done from the footer(the directive) not from the code of the ng-transclude
when I add this transclude(scope, function...) without the line: element.empty(); then the body the content of ng-transclude is duplicated,
when I add element.empty(); then the header and the footer are disappeared and only the content of ng-transculde is displayed.
I want to connect the scope of ng-transclude to the directive's scope without disrupt the UI

In directive's link function add:
link = function (scope, element, attr, controller, transclude) {
transclude(scope.$parent, function(clone, scope) {
var el = element.find('.wfmBody');
el.append(clone);
});
In html file instead of ng-transclude add:
<div class="wfmBody"></div>

Related

how to pass the values of set of input boxes of key value pair to the parent scope in angular js

I have created a directive which contains a map of key value pairs. In edit mode i used to populate the values of entries using ng-repeat, Also a user can add more key value pairs when he press a add button
Below is the code
angular.module('key_value_component',
[])
.directive('keyValuePairs', function ($compile, $templateCache) {
return {
templateUrl: 'key_value.tpl.html',
restrict: 'E',
replace: true,
scope: {
entries: "=ngModel"
},
controller: function ($scope) {
$scope.create_key_value = function () {
$scope.$broadcast('ready-to-render');
}
}
};
})
.directive("keyValueInit", function ($compile, $templateCache) {
return {
templateUrl: 'key_value_init.tpl.html',
restrict: 'E',
replace: true,
link: function (scope, element, attributes) {
scope.$on('ready-to-render', function (event) {
list_select = $compile($templateCache.get("key_value_input.tpl.html"))(scope);
element.parents('.key_value_element').append(list_select);
})
}
}
}).directive("keyValue", function ($compile, $templateCache) {
return {
templateUrl: 'key_value_input.tpl.html',
restrict: 'E',
replace: true,
}});
templates :
key_value_tpl.html
<div class="container-fluid">
<div class="key_value_header">
<button class="btn btn-success btn-add pull-right" type="button" ng-click="create_key_value()">
<span class="glyphicon glyphicon-plus"></span>
</button>
<div class="col-sm-4"><strong>key</strong></div>
<div class="col-sm-4"><strong>value</strong></div>
</div>
<div class="key_value_body">
<key-value ng-repeat="(key,value) in entries"></key-value>
<div class="key_value_element">
<key-value-init></key-value-init>
</div>
</div>
key_value_input.tpl.html
<div class="form-group key_value">
<div class="col-sm-4">
<input class="form-control key_value_key" type="text" ng-value="key" ng-readonly="key"/>
</div>
<div class="col-sm-4">
<input class="form-control key_value_value" type="text" ng-value="value" ng-readonly="value"/>
</div>
<input-remove-button></input-remove-button>
key_value_init.tpl.html
<div></div>
If someone add a new key value pair I want to append its value in entries. A submit event is happening outside the directive in the form. the directive is part of that form.

Creating single custom directive for ng-click to perform multiple controller function

I have the following code:
<div>...
<div class="glyphicon glyphicon-filter ng-click="vm.add()" tabindex="1">
<a href='' tabindex="2"><img id="touch" ng-click="vm.multiply(xyz)"
src="/ui/assets/images/xxx.png"/></a>
<div class="glyphicon glyphicon-filter"ng-click="vm.showId()" tabindex="1" title="Filter">
</div>
..</div>
I want to create a custom single ng-click directive as its recommended for div (ng-click to be used for only buttons). I want to know if there is any way I can create a single directive for all 3 ng-click and call those 3 different functions in link at $apply?
Here you go: http://jsfiddle.net/psevypcs/2/
HTML
<div clicky="test()">test</div>
<div clicky="test2()">test2</div>
AngularJS-Controller
$scope.test = function(){
alert('hy');
};
$scope.test2 = function(){
alert('hy2');
};
AngularJS-Directive
angular.module('myApp')
.directive('clicky', Clicky);
function Clicky() {
return {
restrict: 'A',
scope: {
clicky: '&' // Take yourself as variable
},
link: function(scope, element, attrs){
$(element).on('click', function(e) {
scope.clicky();
});
}
};
}

Reusable modal window directive. How can I pass directive-attributes-values to controller

I want to make a reusable modal-window-directive (i found a pair modal-window examples, but that's not what i want, or they do not work properly).
It should look something like this:
(1) title-, body-text and function-name (for the function, which is binded to the action-button in the template) are defined directly within directive
<my-modal
modal-title="Modal Window Title"
modal-body="This is my Modal Window Body"
click-main-html-action-button="myControllerActionFunction()">
</my-modal>
(2) The HTML-template for modal window must pick up the corresponding values
<div class="panel-default">
<div class="panel-heading">
{{title}}
</div>
<div class="panel-body">
<div class="row">
<div class="form-group col-sm-12">**{{body}}**</div>
</div>
<div class="col-sm-12 text-center">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" data-ng-click="templatestartaction(); $event.stopPropagation()">Start action</button>
</div>
</div>
</div>
(3) Button-function for modal window must be defined In the controller
app.controller('controller', function($scope) {
scope.title = "";
scope.body = "";
$scope.myControllerActionFunction = function () {
console.log('myControllerActionFunction', title);
};
})
The question is: how can I read the attrs values from (1)
(modal-title = "Modal Window Title", etc.) and the function name
(click-main-html-button action = "myControllerActionFunction ()") and
pass it to the model and function definition in the controller
(3), so that it is displayed in the html-template (2)?
I can read the attributes from (1), but I do not know how i pass it in controller.
(4)
app.directive('myModal', function () {
return {
transclude: true,
restrict: 'E',
//template: '<div ng-transclude></div>',
templateUrl: "directives/modal/view/modalWindowTemplate.html"
scope: {
templatestartaction: '&clickMainHtmlActionButton'
},
link: function (scope, element, attrs) {
scope.title = attrs.modalTitle;
scope.body = attrs.modalBody;
}
};
});
You need to define title and body in the controller like
$scope.modalProps = {
title: 'My modal title',
body: 'My modal body'
};
Use this in the html
<my-modal
modal-title="modalProps.title"
modal-body="modalProps.body"
click-main-html-action-button="myControllerActionFunction()">
</my-modal>
And define it for the directive
app.directive('myModal', function () {
return {
transclude: true,
restrict: 'E',
//template: '<div ng-transclude></div>',
templateUrl: "directives/modal/view/modalWindowTemplate.html"
scope: {
templatestartaction: '&clickMainHtmlActionButton'
title: '=modalTitle',
body: '=modalBody'
},
...

How can i watch for change in a angular directive with $translate

Here's Fiddle Link
How can i watch for change in a directive? In this fiddle example using $translate to translate the content. Everything getting changed except the content in Directive.
HTML looks like this-
<div ng-app='demo'>
<div name="info" ng-controller="myctrl">
<label translate="TERMS_LABEL"></label>
<h4 translate="ZIPCODE_LABEL"></h4>
<p translate="LAST_NAME"></p>
<terms-conditions conditions="TERMS_CONDITIONS" checked="checked"></terms-conditions>
<button type="submit" ng-click="changeLanguage('de')" >Spanish</button>
<button type="submit" ng-click="changeLanguage('en')" >English</button>
</div>
directive looks like
demo.directive("termsConditions",['$translate',function($translate){
return {
restrict:"E",
scope:{
checked:'='
},
link: function(scope, element, attr) {
$translate(attr.conditions)
.then(function (translatedValue) {
scope.conditions = translatedValue;
});
},
template:
"<div class='terms row'><span class='col-md-12'>{{conditions}}</span></div><br><input
type='checkbox' ng-model='checked'><span>Yes, I agree to the terms and condtions</span>"
}
}]);
Is there a reason you can't translate in the template like so?
http://jsfiddle.net/UGLjh/75/
demo.directive("termsConditions",['$translate',function($translate){
return {
restrict:"E",
scope:{
checked:'='
},
link: function(scope, element, attr) {
attr.$observe('conditions', function (untranslatedValue) {
scope.conditions = untranslatedValue;
});
},
template:
"<div class='terms row'><span class='col-md-12'>{{conditions | translate}}</span></div><br><input type='checkbox' ng-model='checked'><span>Yes, I agree to the terms and condtions</span>"
}
}]);
If you know that your attribute won't be interpolated need not use $observe; just stick it on the scope like so:
link: function(scope, element, attr) {
scope.conditions = attr.conditions;
},

passing functions and scope vars to directive in an object

I wrote a directive which looks like this:
on parent html:
<cl-sort-n-reverse flip-reverse="flipReverse()" set-key="setKey(key)" sort-key="sortKey" rev="reverse" key="body" title="Content"></cl-sort-n-reverse>
in directive js:
.directive('clSortNReverse', function () {
return {
restrict: 'E',
scope:{
innerKey : '#key',
title : '#title',
inReverse: '=rev',
sortKey:'=',
flipReverse:'&',
setKey:'&'
},
transclude :true,
templateUrl:'../devhtml/common/sortNReverse.html',
link: function (scope, element, attrs) {
}
};
});
in template:
<span>
<div class="btn" ng-if="sortKey!=innerKey" data-ng-click="setKey({key:innerKey});">
{{title}}
</div>
<div class="btn" ng-if="sortKey==innerKey" data-ng-click="flipReverse();">
<b>{{title}}</b>
<i ng-if="inReverse===true" class="fa fa-caret-up"></i>
<i ng-show="inReverse===false" class="fa fa-caret-down"></i>
</div>
</span>
I would really like to be able to insert both functions ans scope level vars like sortKey and reverse to attribute inside one object I can declare in my controller. the answers I found here regarding adding objects to directive attributes all dealt with a simpler case in which the objects encapsulates only simple string or numbers. I'm stumped at how to define that options objects to include $scope level stuff
Is this what you meant?
In your controller:
$scope.sortReverseConfig = {
flipReverse: function() {...},
setKey: function(key) {...},
sortKey: '',
innerKey: $scope.body,
inReverse: $scope.reverse,
title: $scope.content
}
In your html:
<cl-sort-n-reverse config="sortReverseConfig"></cl-sort-n-reverse>
Directive:
.directive('clSortNReverse', function () {
return {
restrict: 'E',
scope:{
config: '='
},
transclude :true,
templateUrl:'../devhtml/common/sortNReverse.html',
link: function (scope, element, attrs) {
}
};
});
Directive template:
<span>
<div class="btn" ng-if="config.sortKey != config.innerKey" data-ng-click="config.setKey({key:config.innerKey});">
{{config.title}}
</div>
<div class="btn" ng-if="config.sortKey == config.innerKey" data-ng-click="config.flipReverse();">
<b>{{config.title}}</b>
<i ng-if="config.inReverse === true" class="fa fa-caret-up"></i>
<i ng-show="config.inReverse === false" class="fa fa-caret-down"></i>
</div>
</span>

Resources