How to replace first element with different html in angular directive - angularjs

Here is my directive:
.directive('iframeOnload', function() {
return {
restrict: 'A',
link: function(scope, elem){
var spinnerElement = angular.element(' <div id="appApprovalSpinner" class="row text-center approve-spinner"><i class="fa fa-spinner fa-pulse fa-5x fa-fw margin-bottom"></i></div>');
elem.replaceWith(spinnerElement);
angular.element('#appApprovalSpinner').addClass('ng-show');
elem.on('load', function(){
angular.element('#appApprovalSpinner').addClass('ng-hide');
});
}
};
});
and here is my html file where to use the directive
<div iframe-onload ></div>
<iframe id="appApprovedId" ng-if="approvalUrl" class="approve-iframe" ng-class="{'app-approved': isAppApproved}" ng-src="{{trustedApprovalUrl}}" iframe-onload></iframe>
I only want to replace the
<div iframe-onload ></div>
with
<div id="appApprovalSpinner" class="row text-center approve-spinner"><i class="fa fa-spinner fa-pulse fa-5x fa-fw margin-bottom"></i></div>'
and keep the iframe as it is because I want onLoad event is called when the iframe is finished loading.
Any suggestion how to replace on the only the div tag but not iframe tag.
Thanks

Instead of doing so much DOM manipulation, you can do this easily with ng-show and ng-hide, and keep track of things with a $scope variable that is assigned by the directive.
Change your directive a bit:
.directive('iframeOnload', function() {
return {
restrict: 'A',
link: function(scope, elem){
scope.ShowSpinner = true;
var spinnerElement = angular.element('<div ng-show="ShowSpinner" class="row text-center approve-spinner"><i class="fa fa-spinner fa-pulse fa-5x fa-fw margin-bottom"></i></div>');
elem.append(spinnerElement);
elem.on('load', function(){
scope.ShowSpinner = false;
});
}
};
});

I made the following changes
Directive:
.directive('iframeOnload', function() {
return {
restrict: 'A',
scope: {
isRequired: '='
},
link: function(scope, elem){
var spinnerElement = angular.element(' <div ng-if="isApprovalRequired" id="appApprovalSpinner" class="row text-center approve-spinner"><i class="fa fa-spinner fa-pulse fa-5x fa-fw margin-bottom"></i></div>');
if ( (angular.element(elem).hasClass('spinner')) && scope.isRequired ) {
elem.replaceWith(spinnerElement);
}
angular.element('#appApprovalSpinner').addClass('ng-show');
elem.on('load', function(){
angular.element('#appApprovalSpinner').addClass('ng-hide');
});
}
};
});
and in the html file I have this
<div class="spinner" iframe-onload is-required="isApprovalRequired"></div>
<iframe id="appApprovedId" ng-if="approvalUrl" class="approve-iframe" ng-class="{'app-approved': isAppApproved}" ng-src="{{trustedApprovalUrl}}" iframe-onload></iframe>
It worked but still need the in there. Note It won't work if there is no tag there
Any solution to make it works without the extra tag ?

Related

Delete json object from directive

hello I want to delete json in angularjs
for the first time I only use ng-repeat directive
<div ng-repeat="artworkItem in artworksItems | filter: {category:'artworks'}| filter:query" class="">
<p>{{artworkItem.name}}</p>
<button ng-click="remove($index)">delete</button>
</div>
controller
ItemFactory.get().then(function(data) {
$scope.artworksItems = data;
});
$scope.remove= function(index){
$scope.artworksItems.splice(index, 1);
}
it works. Then i try to move it with directive.
so my code will be like this
<div ng-repeat="artworkItem in artworksItems | filter: {category:'artworks'}| filter:query" class="">
<grid-artworks data="artworkItem"></grid-artworks>
</div>
directive.html
<div>
<div class=" col-xs-6 col-sm-4 col-md-3 productThumbnail">
<a href="#/Artworks/{{data.id}}" class="">
<img ng-src="{{data.imgUrl}}" alt="{{data.name}}" class="img-responsive">
</a>
<div class="caption">
<p class="title text-center">{{data.name}}</p>
<p class="text-center">{{data.priceTotal}} {{data.curency}}</p>
<button ng-click="remove($index)">d</button>
</div>
</div>
</div>
directive.js
angular
.module('app.directives.gridViewArtworks',[])
.directive('gridArtworks',function()
{
return{
restrict:'E',
scope:{
data: '='
},
transclude:true,
replace:true,
templateUrl:"templates/directives/gridViewArtworks.html",
controller:function($scope){
console.log($scope.data);
}
};
}
);
controller
ItemFactory.get().then(function(data) {
$scope.artworksItems = data;
});
$scope.remove= function(index){
$scope.artworksItems.splice(index, 1);
}
with directive I can't delete the item. Please help me why can't I delete the data.
Pass a callback to your directive from the controller, which will be triggered from removing the element from the array.
scope:{
data: '=',
onRemove: '&'
},
Then when you call the directive:
<grid-artworks data="artworkItem" on-remove="remove(id)"></grid-artworks>
And inside your directive:
<button ng-click="onRemove({id: data.id})">d</button>
And change your remove function in the controller in order to use the id for removing elements from the array, because it's safer than the $index:
$scope.remove= function(id){
$scope.artworksItems.splice($scope.artworksItems.findIndex(el => el.id === id), 1);
}
You could pass index as an attribute.
<grid-artworks data="artworkItem" index="{{$index}}"></grid-artworks>
You'll need to add it to your directive's scope.
scope: {
index: '#',
// ...
And then you can use it.
<button ng-click="remove(index)">d</button>
Alternatively, you should be able to do remove(data):
var index = $scope.artworksItems.indexOf(data);
$scope.artworksItems.splice(index, 1);

losing scope of ng-model when using ng-include (AngularJS)

I am creating android app using ionic and angularjs. In app i used ng-include for include html content in my page.
checkbox.html:
<ul>
<li ng-repeat="opt in $parent.checkboxOptions">
<h4>
<label><input type="checkbox" name="checkbox" ng-model="$parent.checkboxAnswer" value="{{opt.option_value}}">{{opt.option_value}}</label>
</h4>
</li>
</ul>
surveyCtrl.js
$scope.checkboxOptions = params.QuestAnswers;
$scope.next = function(){
console.log($scope.checkboxAnswer);
}
its showing undefined and another thing when i am click on one checkbox its selecting all checkbox's also.
surveyCtrls.js
.directive('question', function ($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, ele, attrs) {
scope.$watch(attrs.question, function(QuesHtml) {
ele.html(QuesHtml);
$compile(ele.contents())(scope);
});
}
};
})
.directive('description', function ($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, ele, attrs) {
scope.$watch(attrs.description, function(DescHtml) {
ele.html(DescHtml);
$compile(ele.contents())(scope);
});
}
};
})
.directive('answers', function ($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, ele, attrs) {
scope.$watch(attrs.answers, function(AnswerHtml) {
ele.html(AnswerHtml);
$compile(ele.contents())(scope);
});
}
};
})
.controller('surveyLoad', function($scope){
var QuestType = SurveyData[QuestionIndex].question_type;
var DrawHTML = {
'QuestionText': 'Some Text',
'QuestionDesc': 'Some Desc',
'QuestAnswers': [{
option_value: 'Red',
}, {
option_value: 'Blue',
}];,
'scope' : $scope
};
checkbox(DrawHTML);
}
})
.controller('nextQuest', function($scope){
$scope.QuestNext = function(){
console.log($scope);
}
});
function checkbox(params){
var $scope = params.scope;
$scope.QuesHtml = "<p>"+params.QuestionText+"</p>";
$scope.DescHtml = "<p>"+params.QuestionDesc+"</p>";
$scope.checkboxOptions = params.QuestAnswers;
$scope.AnswerHtml = "<div ng-include src=\"'surveyTemplate/checkbox.html'\"></div>";
}
survey.html
<div class="row">
<div class="col question_div">
<div class="qus_head">
<p>Question: 1/10</p>
</div>
<h4 class="para"><span question="QuesHtml"></span> </h4>
<div class="qus_footer">
<p>Maxime quis.</p>
</div>
</div>
</div>
<div answers="AnswerHtml">
</div>
<div class="row">
<div class="col button_div">
<ul>
<li><img src="../img/next.png" style="width:70px;float:right" alt="next" ng-controller="nextQuest" ng-click="QuestNext()"></li>
<!-- <center><li><button style="align:center">Stop</button></li></center> -->
<li><img src="../img/pre.png" style="width:70px;float:left" alt="previous" ></li>
</ul>
</div>
</div>
is there any way to get the value of checked checkboxes and prevent to check all other checkboxe's ?
Using ng-includes create it's own scope.
By using the controller as syntax you can overcome this issue.
https://docs.angularjs.org/api/ng/directive/ngController
<div id="ctrl-as-exmpl" ng-controller="Controller as ctrl">
...
<li ng-repeat="opt in ctrl.checkboxOptions">
<h4>
<label><input type="checkbox" name="checkbox" ng-model="ctrl.checkboxAnswer" value="{{opt.option_value}}">{{opt.option_value}}</label>
</h4>
</li>
...
</div>
and in your controller :
$scope.checkboxOptions = params.QuestAnswers;
becomes
this.checkboxOptions = params.QuestAnswers;
and so on.
AngularJS plunker about this syntax :
https://plnkr.co/edit/DB1CpoWLUxQ9U8y558m1?p=preview
Regards,
Eric
You need some correction in the html.
<label><input type="checkbox" name="checkbox" ng-model="opt.option_value">{{opt.option_value}}</label>
With ng-model="$parent.checkboxAnswer" ,all checkbox will share common model.
So,it will get updated at the same time.
So,when you check/uncheck,it will check/uncheck everyone.
And ,you don;t need to use value,angular is used ng-model property for its value evaluation and not value
Yupii...i found the solution..
here is solution:
<ul>
<label ng-repeat="opt in $parent.checkboxOptions">
<li>
<h4>
<label><input type="checkbox" name="checkbox" ng-model="$parent.$parent.selected[opt.option_value]" >{{opt.option_value}}</label>
</h4>
</li>
</label>
</ul>
(function(angular) {
'use strict';
angular.module('MyApp', [])
.controller('AppCtrl', SettingsController1);
function SettingsController1($scope) {
$scope.options = {
'checkboxAnswer': ''
};
$scope.checkboxOptions= [{
type: 'phone',
value: '917xxxxxxxx'
}, {
type: 'email',
value: 'sajankumarv#example.org'
}];
}
})(window.angular);
radio box template file #radiobox.html
<ul>
<li ng-repeat="opt in checkboxOptions">
<h4>
<label><input type="checkbox" ng-model="options.checkboxAnswer" ng-true-value="'{{opt.value}}'" ng-false-value="''">{{opt.type}}</label>
</h4>
</li>
<h1>{{options.checkboxAnswer}}</h1>
</ul>
//in main index.html you simply include this radiobox.html using ng-include directive
<body ng-app="MyApp">
<div ng-controller="AppCtrl">
<div ng-include='"radiobox.html"'></div>
</div>
</body>
I think you are not in isolate scope so you don't have to use $parent for your case.I made a simple working demo for you to understand kindly refer the below link.
https://plnkr.co/edit/aQMZBln5t0Fipwn1qloN?p=preview

how to set focus to anchor tag which is inside a div element and the div element is having ng-show

<div class="test" ng-show="model.data.IsDataLoaded" tabindex="50">
Clear all
</div>
//in the js i am trying to set the focus by below code
$scope.model.data.IsDataLoaded = true;
angular.element("#id1").focus();
Change your ng-show to ng-if and use a directive:
js:
.directive('autoFocus', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
element[0].focus();
}
}
});
html:
<div class="test" ng-if="model.data.IsDataLoaded" tabindex="50">
<a href="" id="id1" ng-click="testData($event)" auto-focus>Clear all</a>
</div>

Toggling a Twitter Bootstrap (3.x) Modal using AngularJS

I've been trying to get a Bootstrap Model to be hidden on load, and then show it after clicking a button, but have been unsuccessful so far. I am pretty new to AngularJS so bear with me if I'm not doing this correctly. Here's what I've got so far:
Modal Angular Directive (modal.js):
angular.module('my.modal', ['modal.html'])
.directive('myModal', function () {
return {
restrict: 'E',
transclude: true,
replace: false,
templateUrl: 'modal.html',
link: function(scope, element, attrs) {
element.modal('hide')
scope.toggleModal = function() {
if (attrs.showModal === true) {
element.modal('hide')
attrs.showModal = false
} else {
element.modal('show')
attrs.showModal = true
}
}
}
};
});
Modal Template (modal.html):
<div id="{{id}}" showModal="false" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">I'm a modal!</h3>
</div>
<div class="modal-body">
<div class="content" ng-transclude></div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="showModal = false">Cancel</button>
</div>
</div>
</div>
</div>
And finally, the button to toggle the modal (index.html):
...
<my-modal>
<p>Some content</p>
</my-modal>
<button class="btn btn-default" type="button" ng-click="toggleModal()">Toggle me!</button>
...
All this does is show the modal on page load (between my header and all the other content, so it's not floating above anything) and the toggle button does not work.
I've managed to get it working by using the Bootstrap 3 Modal properties and dynamically changing styling and classes of the modal directive based on it's show or hide state, though there are no animations:
Modal Angular Directive (modal.js):
angular.module('my.modal', ['modal.html'])
.directive('myModal', [function () {
return {
restrict: 'E',
transclude: true,
replace: false,
templateUrl: 'modal.html',
controller: 'ModalCtrl',
link: function(scope, element, attrs) {
if (attrs.title === undefined) {
scope.title = 'Modal Title Placeholder';
} else {
scope.title = attrs.title;
}
scope.$watch('showModal', function (value) {
if (value) {
scope.displayStyle = 'block';
scope.modalFadeIn = 'in';
} else {
scope.displayStyle = 'none';
scope.modalFadeIn = '';
}
});
}
};
}).controller('ModalCtrl', ['$scope', function ($scope) {
$scope.toggleModal = function() {
$scope.showModal = !$scope.showModal;
};
$scope.$open = function() {
$scope.showModal = true;
};
$scope.$close = function() {
$scope.showModal = false;
};
});
Modal Template (modal.html):
<div role="dialog" tabindex="-1" class="modal fade" ng-init="showModal = false" ng-show="showModal" ng-style="{display: displayStyle}" ng-class="modalFadeIn">
<div class="modal-backdrop fade in" style="height: 100%"> </div>
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">{{title}}</h3>
</div>
<div class="modal-body">
<div class="content" ng-transclude></div>
</div>
</div>
</div>
</div>
The call to open the modal can be done using the open or toggleModal function. A custom button needs to be placed in the modal to close the modal.

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