Delete json object from directive - angularjs

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);

Related

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

Controller function not called from directive template in AngularJS

Directive template (items.html)
<li ng-repeat="item in itemCart">
{{item.title}} <br>
{{item.category}} &nbsp
{{ formatCurrencyFunction({cost: item.price}) }}
</li>
This custom directive is used in Second.html
<h1>
This is Second.
{{header}}
</h1>
<hr>
<ul>
<items-list item-cart="items" format-currency-function="formatPrice(cost)"></items-list>
</ul>
The code for Controller is:
myApp.directive("itemsList", function(){
return{
templateUrl:"contents/Views/Directives/Items.html",
replace: true,
scope:{
itemCart: "=",
formatCurrencyFunction: "&"
},
restrict:"EACM" // E-Element A-Attribute C-Class M-Comments
}
})
myApp.controller('secondController', ['$scope', '$log', '$http','$routeParams', function($scope, $log, $http, $routeParams) {
$scope.formatPrice = function(price){
return "₹ "+parseFloat(price).toFixed(2);
};
$scope.header = 'Second ' + ($routeParams.num || "");
$scope.testSecond = "Second";
$http.get("/items")
.success(function(data){
$scope.items = data;
});
}]);
The function formatPrice is not called from the directive Items.html
What has to be corrected in my code to get it working?
Inside the directive's link function, you'll want to call the method like so:
scope.someFn({arg: someValue});
myApp.directive("itemsList", function(){
return{
templateUrl:"contents/Views/Directives/Items.html",
replace: true,
scope:{
itemCart: "=",
formatCurrencyFunction: "&formatCurrencyFunction"
},
link:function(scope, element, attrs){
scope.formatPrice({arg: 35}); //scope.someFn({arg: 35});
},
restrict:"EACM" // E-Element A-Attribute C-Class M-Comments
}
})
Got this working by using ng-repeat in the Second.html page instead of the directive.
Directive template (items.html)
<li>
{{item.title}} <br>
{{item.category}} &nbsp
{{ formatCurrencyFunction({cost: item.price}) }}
</li>
This custom directive is used in Second.html
<h1>
This is Second.
{{header}}
</h1>
<hr>
<ul>
<items-list item="item" format-currency-function="formatPrice(cost)" ng-repeat="item in items"></items-list>
</ul>
Code in JS file
myApp.directive("itemsList", function(){
return{
templateUrl:"contents/Views/Directives/Items.html",
replace: true,
scope:{
item: "=",
formatCurrencyFunction: "&"
},
restrict:"EACM" // E-Element A-Attribute C-Class M-Comments
}
})
Inside the directive's link function, you need to call the method by applying some event to that attribute
Controller function 'formatCurrencyFunction()' can't be called by just placing it in an expression.
To use the function you need to call it based on an even, in your case ng-init will work.
<li ng-repeat="item in itemCart" ng-init="formatCurrencyFunction({cost: item.price})">
{{item.title}} <br>
{{item.category}}
</li>

How to pass the value to the local scope of the directive?

I'm learning directives, it's cool thing but sometimes a little complicated. Please can somebody explain this:
I have custom directive with template of little form and it own local scope, and want to change the list of items form the main controller.
Please see it:
By clicking on change button I open a custom directive with input form template
<body ng-controller="testCtrl">
<h1>Hello Plunker!</h1>
<ul>
<li ng-repeat="item in list">
<div> {{item}} </div>
<button ng-click="edit()">Change</button>
<change ng-if='editable'></change>
</li>
</ul>
</body>
"Change" is the custom directive with the input form inside the other Html file
.directive('change', function(){
return {
restrict: "E",
replace: true,
scope: {
show: '='
},
templateUrl: "other.html"
}
})
Also there is another directive inside "change" directive. It's a button which I want to use inside "change" directive and inside my main controller. I can see my item list only from scope.$parent.item, but how to pass it in the function of my button directive?
How can I implement this?
.directive('save', function(){
return {
restrict: "E",
replace: true,
template: ' <button class="btn btn-sm btn-warning" ng-click="saving(item)">SAVE</button>',
link: function(scope,element,attr){
scope.saving = function(item){
console.log(item);
console.log(scope.$parent.item)
}
}
}
})
Please see the example: Plnkr
P.S. Sorry for my explanation, I hope that everything is clear
Simply pass in the item to each of your directives that need access to it. For example:
<li ng-repeat="item in list">
//snip
<save item="item"></save>
//snip
</li>
And then define your directive to bind the attribute to the scope:
.directive('save', function(){
return {
//snip
scope: {
item: '=' //two-way binding to 'scope.item'
},
//snip
link: function(scope, element, attr){
scope.saving = function() {
console.log(scope.item);
}
};
});
In angularjs, you have the $emit event.
Dispatches an event name upwards through the scope hierarchy notifying the registered $rootScope.Scope listeners.
$rootScope.Scope
HTML
<body ng-controller="testCtrl">
<h1>Hello Plunker!</h1>
<ul>
<li ng-repeat="item in list">
<div> {{item}} - <input type="text" ng-model="item">
<button ng-click="edit()">Change</button>
</div>
<div>
<change ng-if='editable'></change>
</div>
</li>
</ul>
</body>
Directive
directive('save', function(){
return {
restrict: "E",
replace: true,
template: ' <button class="btn btn-sm btn-warning" ng-click="saving(item, $parent.$index)">SAVE</button>',
link: function(scope,element,attr, controller){
scope.saving = function(item, index){
//Build our object with the index of $scope.list which is updated & the item value
var obj = {
index: index,
item: item
};
//Emit a 'change' event, and we pass our object data
scope.$emit('change', obj)
}
}
}
})
In the "change" directive, we use $emit to pass event, and to notify our $rootScope.Scope.
In the "change" directive template, you can see that we pass the $parent.$index and not the $index, in order to get the current item of the list.
Controller
controller('testCtrl', function($scope){
$scope.list = [1,2,3,4,5,6,7,8,9];
//Listen for 'change' event
$scope.$on('change', function(event,value){
//Set to the list value.index our value.item
$scope.list[value.index] = value.item;
});
$scope.editable = false;
$scope.edit = function(){
$scope.editable = !$scope.editable;
}
})

angular does not load my directive

I newly start to use angular.but I have some problem to loading my directive.
I want to load my directive as soon as page loaded.
where I load data-show directive
<div class="row">
<div class="col-md-12">
<article class="row" ng-controller="DataCtrl">
<input type="button" ng-click="getDataList()" >
<h1>Some Content Here</h1>
<ul id="home" bread-crumbs></ul>
<ul class="thumbnails">
<li ng-repeat="data in list" class="col-md-5">
<show-data data="data"/>
</li>
</ul>
</article>
</div>
</div>
showData directive:
app.directive('showData', function () {
return{
restrict: 'E',
replace:true,
templateUrl: 'views/directives/datas.directive.html',
scope: {
data: "="
},
controller:'DataCtrl'
}
})
and template I used in:
<div class="well hoverwell">
<div class="row">
<h2 class="col-md-4">{{data.name}}</h2>
</div>
<div class="row">
<span class="col-md-1">Code:</span>
<span class="col-md-1">{{data.id}}</span>
</div>
<div class="row">
<span class="col-md-1">accountability:</span>
<span class="col-md-1">{{data.parent}}</span>
</div>
<div class="row">
<span class="col-md-1"> :</span>
<span class="col-md-1">{{data.definition}}</span>
</div>
</div>
and my controller
'use strict';
angular.module('app')
.controller('DataCtrl', function ($scope, DataService, $log) {
$scope.getDataList = function () {
var list = DataService.getDataList(1);
list.then(
function (result) {
$log.info(result);
$scope.dataList = result;
}, function (status) {
$log.error(status)
$scope.msg = "error " + status + " has been occur,please report to admin ";
});
};
});
and when I run my app it does not work .
when I watch it in chorome development tools my directive is comment
what is my problem.How can I call this directive as soon as page load.
thx
As you already noticed, you see empty list because your dataList in ng-repeat is not filled yet.
But you have some errors in your code:
First of all - you should never use one controller twice. So you need to create separate controller for your directive.
replace directive parameter is deprecated, better not to use it.
In your DataCtrl you set the dataList variable: $scope.dataList = result;, but in HTML you refer to list variable: <li ng-repeat="data in list" class="col-md-5">.
Maybe that example will help you to figure out with your code.

Angularjs : accessing service methods from directive's link function

i have a directive, and in its link function i want to access methods from a service. My code for directive is
AppDirectives.directive('feed',['FeedService',function() {
return {
restrict : 'AE',
scope : {
feedLike: '&',
feedItem : '=',
feedDislike :'&',
feedsArray :'=',
},
templateUrl :'resources/views/templates/feedTemplate.html',
link : function(scope,element,feedService){
console.debug("linking now");
scope.likeComment = function(commentUid){
console.debug("comment liked :"+commentUid);
};
scope.addComment = function(referenceFeedUid){
console.debug("commentText : "+scope.commentText);
var comment = {
user : "guest",
feedText : scope.commentText
};
feedService.addComment(comment,referenceFeedUid).then(function(response){
console.debug("response ; "+response);
// $scope.feeds.unshift(response);
});
};
},
replace : true,
};
}]);
and my service code is
.factory('FeedService',function($http){
return {
postFeed : function (feed){
/*$http.post('/feed/add',feed).success(function(response){
console.debug("added "+response);
}).error(function(){
console.debug("error adding feed");
});*/
return $http.post('/feed/add',feed).then(function(response){
return response.data;
});
},
getFeeds : function(){
return $http.get('/feed/get');
},
likeFeed : function(feedUid){
return $http.get('/feed/'.concat(feedUid).concat('/like')).then(function(response){
return response.data;
});
},
dislikeFeed : function(feedUid){
return $http.get('/feed/'.concat(feedUid).concat('/dislike')).then(function(response){
return response.data;
});
},
addComment : function (comment,referenceUid){
var targetUrl = '/feed/'.concat(referenceUid).concat('/comment');
return $http.post(targetUrl,comment).then(function(response){
return response.data;
});
},
};
});
when i call the add comment from directive's link, i am getting following error on firebug console.
TypeError: Object #<Object> has no method 'addComment'
at Object.scope.addComment (http://localhost:8080/feed/resources/js/directives.js:53:21)
at http://localhost:8080/feed/resources/js/lib/angular/angular.js:6193:19
at http://localhost:8080/feed/resources/js/lib/angular/angular.js:12684:13
at Object.Scope.$eval (http://localhost:8080/feed/resources/js/lib/angular/angular.js:7840:28)
at Object.Scope.$apply (http://localhost:8080/feed/resources/js/lib/angular/angular.js:7920:23)
at HTMLButtonElement.<anonymous> (http://localhost:8080/feed/resources/js/lib/angular/angular.js:12683:17)
at http://localhost:8080/feed/resources/js/lib/angular/angular.js:1926:10
at Array.forEach (native)
at forEach (http://localhost:8080/feed/resources/js/lib/angular/angular.js:110:11)
at HTMLButtonElement.eventHandler (http://localhost:8080/feed/resources/js/lib/angular/angular.js:1925:5)
here is my directive template
<ul class="media-list">
<li class="media">
<a class="pull-left" href="#"><img class="media-object" src="resources/images/holder.png" style="height:64px; width:64px;" alt="img"></a>
<div class="media-body">
<span><h4 class="media-heading">{{feedItem.userUid}}</h4>{{ feedItem.time | date:medium }}</span>
<h5>{{feedItem.feedText}}</h5><h3></h3>
<p> <a ng-click="feedLike(feedItem.feedLike)">Like </a> {{feedItem.like}}
<a ng-click="feedDislike(feedItem.feeddisLike)">Dislike</a> {{feedItem.dislike}}
</p>
<div ng-repeat = "comment in (feedsArray | filter:{referenceGroupId:feedItem.uid})">
<div class="media">
<a class="pull-left" href="#"><img class="media-object" src="resources/images/holder.png" style="height:64px; width:64px;" alt="img"></a>
<div class="media-body">
<span><h4 class="media-heading">{{comment.userUid}}</h4>{{ comment.time | date:medium }}</span>
<h5>{{comment.feedText}}</h5><h3></h3>
<p> <a ng-click="likeComment(comment.uid)">Like </a> {{comment.like}}
<a ng-click="commentDislike(comment.uid)">Dislike</a>{{comment.dislike}}
</p>
</div>
</div><br/>
</div>
<div>
<input type="text" id="commentBox" ng-model="commentText"/>
<button class="btn btn-success" ng-click="addComment(feedUid)">Comment</button>
</div>
</div>
</li>
</ul>
what i am trying to do is that i want to access the addCommennt method from service. how can i fix it or is there any way that i can acess the service methods from inside the directive link function.
Thanks in advance.
regards,
Instead of declaring the service in the link function, declare it when you are defining the directive:
So here:
AppDirectives.directive('feed',['FeedService',function(feedService) {
Then the feedService will be available to call inside the link function. The link function parameters are specifically defined as scope, element, attrs, ctrl so there is no straight dependency injection happening there (AFAIK).

Resources