ng-click directive not working on button - angularjs

html
<button class="btn btn-primary" ng-click="tasks.passivate()">
Passivate <i class="fa fa-spinner fa-spin" ng-if="tasks.passivating"></i>
</button>
task.controller
function passivate() {
console.log('passivate');
vm.passivating = true;
return taskService
.passivate(vm.task.id)
.then(function (task) {
vm.passivating = false;
})
.catch(alertError);
}
The button does not work, passivate does not appear in the console.

When referencing something from the controller in the view, you have to use the $scope. Your function definition should be:
$scope.tasks.passivate = function() {
//...
}

your button, I believe is part of the view which is now bound to a controller. The controller creates a scope object which actually glues your view and the controller. So if you want to invoke a function from the view it should have the scope reference. Hence $scope should be used:-
$scope.tasks.passivate = function(){
//----your logic goes here.
}
Its good to see that you are using tasks.passivate as it will save your from prototypal inheritance. To know more:- Click here

Related

How to change the name of the button? Ng-show, ng-if, ng-click does not work?

I am trying to change the name of the button from Hold Payment to Unhold Payment, it should first check the status of the checkstatus.is_holdpayment and then execute the function userhold_payment(). I tried various things, ng-show, ng-if but the name of the button does not change on click. On click it should go, Hold, Unhold, Hold, Unhold and also execute the same function, userhold_payment(). I want to change the name of the button using AngularJS. What is the mistake. Here is the main.html
<div ng-init="check_status()">
<button type="button" ng-if="checkstatus.is_hold_payment" ng-click="userhold_payment();" class="btn-success btn-lg hold_payment_html" style="margin-top:7px; font-size:16px">Hold</button>
<button type="button" ng-if="!checkstatus.is_hold_payment" ng-click="userhold_payment();" class="btn-success btn-lg hold_payment_html" style="margin-top:7px; font-size:16px">UnHold</button>
</div>
Here is the Controller for the function.
$scope.userhold_payment = function() {
$http.get('http://localhost/ngaffiliate/api/payment/change_hold_payment_status')
.then(function(response) {
console.log('I called');
$scope.userhold = response.data;
console.log($scope.userhold.is_hold_payment);
});
};
//this will call when ever your controller reinstance
($scope.check_status = function() {
$http.get('http://localhost/ngaffiliate/api/payment/check_payment_status')
.then(function(response) {
console.log('I called now')
$scope.checkstatus = response.data;
// console.log(response);
console.log($scope.checkstatus.is_hold_payment);
if($scope.checkstatus.is_hold_payment=="0")
$scope.checkstatus.is_hold_payment = true;
else($scope.checkstatus.is_hold_payment=="1")
$scope.checkstatus.is_hold_payment = false;
$scope.checkstatus.is_hold_payment =!$scope.checkstatus.is_hold_payment;
console.log($scope.checkstatus.is_hold_payment);
});
})();
As I already mentioned in my comment, you should probably call $scope.check_status() in your $scope.userhold_payment() function, since the function doesn't normally change the value of the $scope.checkstatus.is_hold_payment variable. I also removed the line where you reversed the variable's value.
Plunker here to demonstrate: https://plnkr.co/edit/SWpdHGaNWIkyIWSvHyUU?p=preview
Try using this:
<button type="button" ng-click="userhold_payment();" class="btn-success btn-lg hold_payment_html" style="margin-top:7px; font-size:16px">{{checkstatus.is_hold_payment ?? "Hold": "Unhold"}}</button>

angularjs -how to clear the form data from a clear button outside sitting outside the form

I have a form with a submit button which works fine. However I need to clear the form data from a clear button which is sitting outside the form on top right of the page. The clear button exist in a parent controller and sits above the form in top right header. The form sent from the clear button always comes up as undefined, which is because the clear button is not part of the form.
How do I pass the same instance of the form to clear? How do I clear the data? If this is a design issue I still need a workaround.
Here is a fiddle I have created to mimic that. Any help will be appreciated.
https://jsfiddle.net/SobDan/vj67rtb2/
<div ng-app>
<div class="col-md-10">
<h2>Todo</h2></div>
<div class="col-md-2">
<button class="btn pull-right" ng-click="clear(TodoForm)"> Close</button>
</div>
<br>
<div ng-controller="TodoCtrl">
<form name="TodoForm" ng-submit="addTodo()" name="testForm">
<input type="text" ng-model="todoText" size="30" placeholder="add new todo here">
<input class="btn-primary" type="submit" value="add">
</form>
</div>
function MainCtrl($scope) {
$scope.clear = function(form) {
alert(form); // the form is undefined
if (form.$dirty)
form.setPristine(); // clean this form
else
alert("form not dirty");
};
};
function TodoCtrl($scope) {
$scope.todoText = "test";
$scope.addTodo = function() {
alert("Submitted");
$scope.todoText = "";
// submit logic works fine
};
}
You should use $broadcast to communicate between controllers rather than trying to access the form which is outside scope.
Here is the fiddle and the explanation below
$broadcast function is used to broadcast events to all child $scope. Any interested child $scope can register to listen for the event using $on function. This functionality is used to communicate between controllers.
In your case, we signal to clear the form by broadcasting an event called clearForm from $rootScope. The TodoCtrl $scope listening on the event clearForm will receive a signal to clear form fields.
app.controller("MainCtrl", function($scope, $rootScope) {
$scope.clear = function(form) {
$rootScope.$broadcast("clearForm");
};
});
app.controller("TodoCtrl", function($scope) {
$scope.$on("clearForm", function() {
if ($scope.testForm.$dirty) {
$scope.testForm.$setPristine();
$scope.todoText = "";
} else {
alert("form not dirty");
}
});
});
AngularJS 1.1.x +
$scope.form.$setPristine() is only available from AngularJS version 1.1.x.
$setPristine() will only set the form status to pristine and will not clear the form field. You need to manually clear it by nullifying the $scope variables which will be reflected on the screen.
if ($scope.testForm.$dirty) {
$scope.testForm.$setPristine();
$scope.todoText = "";
}
AngularJS 1.0.x +
$setPristine function is not available in 1.0.x version.
The example Fiddle in your question seem to be configured to 1.0.x
In 1.0.x you simply clear the $scope variables
$scope.$on("clearForm", function() {
$scope.todoText = "";
});

Create new isolated scope programmatically

I am trying to create popup html to go into a leafletjs marker popup.
I have the following partial:
<div class="popup">
<div class="pull-right">
<a class="popup-info" ng-click="onInfoClicked()">
<i class="fa fa-info-circle"></i>
</a>
</div>
<div class="popup-title">
{{title}}
</div>
<div class="popup-subtitle">
{{subtitle}}
</div>
</div>
and the following directive:
app.directive('leafletPopup', function() {
return {
restrict: "A",
templateUrl: "app/partials/leaflet-popup.html",
scope: {
feature: '=',
popupInfo: '&'
},
controller: function ($scope) {
$scope.title = $scope.feature.properties.title;
$scope.subtitle = $scope.feature.properties.description;
$scope.onInfoClicked = function() {
$scope.popupInfo({feature: feature});
}
}
};
});
I have a controller that provides a function to generate the html for each marker that I am going to place on the map:
function html(feature) {
var el = angular.element('<div leaflet-popup="feature" popup-info="onPopupInfo(feature)"></div>');
var compiled = $compile(el);
var newScope = $scope.$new(true); // create new isolate scope
newScope.feature = feature; // inject feature into the scope
newScope.onPopupInfo = function(feature) { // inject function into scope
// do something with the click
showFeatureDetails(feature);
}
compiled(newScope);
return el[0];
}
Works perfectly. Great right?
I have read in a couple of places that its not recommended to create your own scope manually as you have to make sure you also destroy it manually.
Lets say I have a bunch of markers on my map, and each has a popup. Do I need to track all the new scopes I create in my controller and call destroy on them? When? Only if my marker gets removed from the map?
I could just skip angular and build the entire html element with jquery and attach the onclick to a function, but that is also not pretty. And why skip angular?
Seems overly complicated, which probably means I am doing this the hard way ;)

How can I dynamically unlink a directive in angularJS?

I don't know if there's a way to handle this in angularjs, but I want to be able to dynamically unlink/link a directive.
For example, I have a link which goes to a user's profile page:
<a ui-sref="users({user_id: post.user.id})">{{post.user.username}}</a>: {{post.text}}
Which correctly creates a link: href="/users/5"
But if that post is anonymous, then there's no user id for that post, creating a link: href="/users/", which is not what I want.
The only solution I was able to find was the following:
<span ng-if="post.user.id">
<a ui-sref="users({user_id: post.user.id})">{{post.user.username}}</a>: {{post.text}}
</span>
<span ng-if="!post.user.id">
<a href>{{post.user.username}}</a>: {{post.text}}
</span>
Which wouldn't be so bad if I weren't putting all this nonsense throughout my entire application. Is there a way to create a simple directive that does the following:
<a ui-sref="({user_id: post.user.id})" unlink="{'ui-sref': !post.user.id}">post.user.username</a>: {{post.text}}
And it would link/unlink ui-sref depending on the value of post.user.id? I could try to create a directive that modifies href, but that would be a mess conflicting with ui-sref. Also, an unlink directive would be more extensible because we could effectively use it with any directive. Any ideas?
Here is a plunker: http://plnkr.co/edit/dus2VixdzhUJtakOs4WR?p=preview
I made a directive that adds a 'click' event listener before ui-sref:
If the expression is evaluated to false then stopImmediatePropagation is called.
I use the native addEventListener because of this issue.
Directive:
app.directive('unlink',function($parse){
return {
compile: function (tElm,tAttrs) {
var fn = $parse(tAttrs.unlink);
return {
pre: function (scope,elm){
elm[0].addEventListener('click', function(e){
if(! fn(scope)) {
e.stopImmediatePropagation();
}
});
}
}
}
}
});
HTML:
<a ui-sref="home" unlink="expression"> Click </a>

Add an event on ng-show

i'm not an angular master and i try to do something.
Suppose a fonctionality like "i like / i dislike".
When you're on an article, you can click on the "i like" button. If you already liked the article, this button is hidden and the "i don't like anymore" appears.
<button ng-hide="like" class="btn btn-success btn-xs pull-right" ng-click="iLike()">I like</button>
<button ng-show="like" class="btn btn-danger btn-xs pull-right" ng-click="notLike()">Don't like anymore</button>
Everything work as expected when i reload the page but not on click action.
Basically my iLike function looks like and i think miss behavior comes from a missing return or an event to fire :(
$scope.iLike = function(){
##hereIDoAnAPICalls##, function(){
$scope.like = false;
}, function(){
$scope.like = true;
}
}
Try to wrap scope variable assignment into apply, I think it could help since API call is probably asynchronous and click event is invoked from outside of angular
$scope.iLike = function() {
APIcall.then(function () {
$scope.$apply(function() {
$scope.like = false;
});
}, function () {...the same...});
};

Resources