Confirm dialog box in angularjs - javascript

How can I apply confirm dialog box in below button in angularjs ?
<button class="btn btn-sm btn-danger" ng-click="removeUser($index)">Delete</button>
Just like this.
<span><a class="button" onclick="return confirm('Are you sure to delete this record ?')" href="delete/{{ item.id }}">Delete</span>
Update
Currently I am doing it like this
function removeUser(index) {
var isConfirmed = confirm("Are you sure to delete this record ?");
if(isConfirmed){
vm.users.splice(index, 1);
}else{
return false;
}
};

Here is the snippets,
how your HTML should be,
<button class="btn btn-sm btn-danger" ng-confirm-click="Are you sure to delete this record ?" confirmed-click="removeUser($index)">Delete</button>
Please Include this directive in your custom angularjs file,
app.directive('ngConfirmClick', [
function(){
return {
link: function (scope, element, attr) {
var msg = attr.ngConfirmClick || "Are you sure?";
var clickAction = attr.confirmedClick;
element.bind('click',function (event) {
if ( window.confirm(msg) ) {
scope.$eval(clickAction)
}
});
}
};
}])
Your angular scope based on your delete function mentioned above,
$scope.removeUser = function(index) {
vm.users.splice(index, 1);
}

$scope.removeUser= function (ind){
if (confirm("Are you sure?")) {
alert("deleted"+ s);
$window.location.href = 'delete/'+ s;
}
}
http://jsfiddle.net/ms403Ly8/61/

I would separate the message bit from the delete action bit, that way you could reuse the confirm bit in other parts of your app:
I use a directive like so:
angular.module('myModule').directive("ngConfirmClick", [
function() {
return {
priority: -1,
restrict: "A",
link: function(scope, element, attrs) {
element.bind("click", function(e) {
var message;
message = attrs.ngConfirmClick;
if (message && !confirm(message)) {
e.stopImmediatePropagation();
e.preventDefault();
}
});
}
};
}
]);
then have your controller function with the delete action:
$scope.removeUser(index) {
//do stuff
}
and in the View I would use ng-click:
<span><a class="button" ng-confirm-click="Are you sure?" ng-click="removeUser(item.id}}">Delete</span>
hope it helps.

You can try this plunker: http://plnkr.co/edit/xJJFxjYeeHmDixAYPu4c?p=preview
You can create a directive for the dialog.
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $window) {
$scope.delete = function(id) {
$window.location.href = 'delete/'+ id;
}
});
app.directive('ngConfirmClick', [
function(){
return {
link: function (scope, element, attr) {
var msg = attr.ngConfirmClick || "Are you sure?";
var clickAction = attr.confirmedClick;
element.bind('click',function (event) {
if ( window.confirm(msg) ) {
scope.$eval(clickAction)
}
});
}
};
}])

Related

How do I return promise to satisfy the directive?

I have the following code and I have tried just bout everything to return a promise that would work with the directive. I have even tried returning the response data and return $q.when(data) and nothing. Ive tried reading on promises and this one is a bit different then Ive read. Something I'm missing?
myApp.controller('smsCtrl', function($scope){
$scope.sendSMS = function(){
let sms = {'number': $scope.number ,'message': $scope.message};
serviceNameHere.sendSMS(sms).then(function(response){
$scope.smsSuccessMsg = "Message Sent Successfully";
}, function(response){
$scope.smsErrorMsg = response.data['message'];
});
};
})
myApp.directive('onClickDisable', function() {
return {
scope: {
onClickDisable: '&'
},
link: function(scope, element, attrs) {
element.bind('click', function() {
element.prop('disabled',true);
scope.onClickDisable().finally(function() {
element.prop('disabled',false);
})
});
}
};
});
The following html
<div ng-controller="smsCtrl">
<-- field inputs here --></-->
<button type="button" class="btn btn-primary" on-click-disable="sendSMS()">SEND</button>
</div>
JSfiddle Example
There is no need to have a special directive for this. Simply use ng-disabled and ng-click:
<div ng-controller="smsCtrl">
<!-- field inputs here -->
<button ng-click="sendSMS()" ng-disabled="pendingSMS">
SEND
</button>
</div>
In the controller:
myApp.controller('smsCtrl', function($scope, serviceNameHere){
$scope.sendSMS = function(){
let sms = {'number': $scope.number ,'message': $scope.message};
$scope.pendingSMS = true;
serviceNameHere.sendSMS(sms).then(function(response){
$scope.smsSuccessMsg = "Message Sent Successfully";
}, function(response){
$scope.smsErrorMsg = response.data['message'];
}).finally(function() {
$scope.pendingSMS = false;
});
};
})
When the SMS message starts, the controller sets the pendingSMS flag to disable the Send button. When the service completes, the flag is reset and the button is re-enabled.

AngularJs ng-repeat didn't updated after changing $scope variable

I have table with item list and modal window where i can change drug properties. When properties changed that drug have to remove from that list. But it's didn't remove.
Modal window:
$modal.open({
templateUrl:'app/interactions/partials/modals/resolveDrug.html',
controller: 'DrugsListController',
scope: $scope
}).result.then(function(data){
var index = _.findIndex($scope.drugs, {_id: data._id});
$scope.drugs.splice(index,1);
}
i think element didn't remove 'cause when i open modal window i create copy of my scope and then work with copy..
On that form i have refresh button that refresh all list.
$scope.refresh= function() {
$scope.drugs = UnresolvedDrugsService.query();
};
and it's didn't work too. I think it happens because i work with copy too.
Okey, i try to emit some event
$modal.open({
templateUrl:'app/interactions/partials/modals/resolveDrug.html',
controller: 'DrugsListController',
scope: $scope
}).result.then(function(data){
var index = _.findIndex($scope.drugs, {_id: data.data._id});
$rootScope.$emit('refreshDrug', index);
}
$rootScope.$on('refreshDrug', function(index){
$scope.drugs = [];
$scope.drugs.splice(index,1);
// $scope.drugs= UnresolvedDrugsService.query();
});
And it's not working.
Can you help me and describe what i doing wrong, thx!
UPD
modal window html
<form role="form" name="resolveDrugForm" ng-submit="saveResolvedDrug(drug) && $close(drug)">
........{some code, input's and label}......
<input type="submit" class="btn btn-primary" value="{{'COMMON.SAVE' | translate}}"/>
<button type="button" class="btn btn-default" ng-click="$dismiss()" >{{'COMMON.CANCEL' | translate}}</button>
code of ng-repeat
<tr ng-repeat="drug in drugs" ng-click="resolveDrug($index)">
<td>{{drug.productName || drug.description }}</td>
<td>{{drug.aiccode }}</td>
</tr>
and all method of controller:
$rootScope.$on('refreshDrug', function(index){
// $scope.drugs = [];
$scope.drugs.splice(index,1);
// $scope.drugs= UnresolvedDrugsService.query();
});
$scope.drugs= UnresolvedDrugsService.query();
$scope.refresh= function() {
$scope.drugs= UnresolvedDrugsService.query();
};
$scope.spliceEl = function(data){
var index = _.findIndex($scope.drugs, {_id: data._id});
$scope.drugs.splice(index,1);
return true;
};
$scope.saveResolvedDrug = function(drug){
DrugsService.addResolvedDrug(drug).then(function(data){
var index = _.findIndex($scope.drugs, {_id: data.data._id});
if(data.data.ingredients && data.data.ingredients.length > 0){
data.data.ingredients = JSON.parse(data.data.ingredients);
}
$scope.drugs.splice(index,1);
return true;
});
return true;
};
$scope.resolveDrug=function(index){
$scope.drug={};
var drugs = $scope.drugs;
$scope.drug=angular.copy($scope.drugs[index]);
var scope=$scope;
$modal.open({
templateUrl:'app/interactions/partials/modals/resolveDrug.html',
controller: 'DrugsListController',
scope: $scope
}).result.then(function(data){
console.log($scope.drugs);
var index = _.findIndex($scope.drugs, {_id: data._id});
//$scope.drugs.splice(index,1);
console.log($scope.drugs);
$rootScope.$emit('refreshDrug', index);
}, function(data){
}).finally(function(data){
$scope.refresh();
});
}
I didn't know why it didn't works with events. But if saveDrug in modal result but sumbit form - work fine.
Now code looks like
$scope.resolveDrug=function(index){
$scope.drug={};
var drugs = $scope.drugs;
$scope.drug=angular.copy($scope.drugs[index]);
var scope=$scope;
$modal.open({
templateUrl:'app/interactions/partials/modals/resolveDrug.html',
controller: 'DrugsListController',
scope: scope,
resolve: {
drug: function () {
return $scope.drug;
}
}
}).result.then(function(data){
}, function(data){
}).finally(function(data){
});
}
$scope.saveResolvedDrug = function(drug){
DrugsService.addResolvedDrug(drug).then(function(data){
var index = _.findIndex($scope.drugs, {_id: data.data._id});
if(data.data.ingredients && data.data.ingredients.length > 0){
data.data.ingredients = JSON.parse(data.data.ingredients);
}
$scope.drugs.splice(index,1);
return true;
});
return true;
};

How do I implement a cancellable editable field in Angular?

In my model, I have a field that I need several controls to bind to. One of these controls is a text box. The text box should not directly edit the field, but instead it should allow the user to type and then either commit the changes or cancel. If any other operation occurs then it should overwrite any changes in the text field. One constraint is that there are other UI components that change the value and do not have access to the local scope.
I implemented the desired behavior with a directive: http://jsfiddle.net/fLxjjmb7/3/
It works as intended, but I feel that there must be a better way to do this. Any ideas?
<div ng-app="app" ng-controller="controller">
<div>{{foo}}</div>
<button ng-click="increment()">increment</button>
<button ng-click="decrement()">decrement</button>
<br />
<div shadow="foo">
<input type="text" ng-model="foo" />
<button ng-click="commit()">update</button>
<button ng-click="cancel()">cancel</button>
</div>
</div>
var app = angular.module('app', []);
var controller = app.controller('controller', function ($scope) {
$scope.foo = 1;
$scope.increment = function () { ++$scope.foo; };
$scope.decrement = function () { --$scope.foo; };
});
var directive = app.directive('shadow', function() {
return {
scope: true,
link: function(scope, el, att) {
scope.$parent.$watch(att.shadow, function (newValue) {
scope[att.shadow] = newValue;
});
scope.commit = function() {
scope.$parent[att.shadow] = angular.copy(scope[att.shadow]);
};
scope.cancel = function() {
scope[att.shadow] = angular.copy(scope.$parent[att.shadow]);
};
}
};
});
Think you are complicating this a bit :)
View:
<div ng-controller="ShadowController">
<h1>{{foo}}</h1>
<div>
<button ng-click="increment()">increment</button>
<button ng-click="decrement()">decrement</button>
</div>
<div>
<input type="text" ng-model="tempFoo" />
<button ng-click="commit()">update</button>
<button ng-click="cancel()">cancel</button>
</div>
</div>
Controller:
.controller('ShadowController', function ($scope) {
$scope.foo = 1;
$scope.increment = function () {
++$scope.foo;
$scope.cancel();
};
$scope.decrement = function () {
--$scope.foo;
$scope.cancel();
};
$scope.commit = function () {
$scope.foo = parseFloat($scope.tempFoo);
};
$scope.cancel = function () {
$scope.tempFoo = $scope.foo;
};
$scope.cancel();
});
An even fancier way would be to keep track of changes to the temporary value and only enable commit/cancel buttons if there is a diff between original and temp.
View:
<div ng-controller="ShadowControllerAdv">
<h1>{{data.original}}</h1>
<div>
<button ng-click="increment()">increment</button>
<button ng-click="decrement()">decrement</button>
</div>
<div>
<input type="text" ng-model="data.edit" />
<button ng-click="commit()" ng-disabled="!state.hasChanged">update</button>
<button ng-click="reset()" ng-disabled="!state.hasChanged">cancel</button>
</div>
</div>
Controller:
.controller('ShadowControllerAdv', function ($scope) {
var _dataWatcher;
$scope.data = {
original: 1
};
$scope.state = {
hasChanged: false
};
function _startWatcher() {
_dataWatcher = $scope.$watch('data.edit', function (newValue, oldValue) {
if (newValue !== oldValue) {
$scope.state.hasChanged = true;
} else {
$scope.state.hasChanged = false;
}
}, true);
}
function _stopWatcher() {
if (!_dataWatcher) {
return;
}
_dataWatcher();
}
$scope.reset = function () {
_stopWatcher();
$scope.data.edit = $scope.data.original;
$scope.state.hasChanged = false;
_startWatcher();
}
$scope.commit = function () {
_stopWatcher();
$scope.data.original = parseFloat($scope.data.edit);
$scope.reset();
}
$scope.increment = function () {
$scope.data.original = $scope.data.original + 1;
$scope.reset();
};
$scope.decrement = function () {
$scope.data.original = $scope.data.original - 1;
$scope.reset();
};
$scope.reset();
});

Preventing user from entering alphabet & push the model into array

I'm using angular & trying to prevent the user from entering alphabet into text field and at the same item push the model onto array. But the logic doesn't seem to work perfectly and sometimes allows alphabets. How can I prevent special characters like $,% from being entered ?
HTML
<ul>
<li ng-repeat="item in arr track by $index">
<input type="text" number ng-change="itemChange()" ng-model="item" />
<button ng-click="add()">Add Item</button>
</li>
</ul>
JS
app.directive('number', function(){
return {
require: 'ngModel',
link: function(scope, elem, attr, ctrl){
elem.bind('keyup', function(e) {
console.log(e)
var text = this.value;
this.value = text.replace(/[a-zA-Z]/g,'');
});
}
};
})
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.arr = [];
//Initialize with one element
$scope.arr[0] = '';
//Push when there is a change in the input
$scope.itemChange = function() {
$scope.arr[this.$index] = this.item;
}
//Add an empty item at the end
$scope.add = function() {
$scope.arr[$scope.arr.length] = '';
}
});
Demo : http://plnkr.co/edit/t8OE5uJ578zgkiUTjHgt?p=preview
Try this:
app.directive('alphabetonly', function(){
return {
require: 'ngModel',
link: function(scope, elem, attr, ctrl){
ctrl.$parsers.push(function(inputValue) {
var transformedInput = inputValue.replace(/[^\w\s]/gi,'');
if (transformedInput != inputValue) {
ctrl.$setViewValue(transformedInput);
ctrl.$render();
}
return transformedInput;
});
}
};
})
See plunk.

The attributes passed to directive in AngularJS change only into directive scope but not outside

I want to use a directive to customize my code.
I have created a button to switch isCollapsedUpload flag defined in the controller as: #scope.isCollapsedUpload=false.
When the user presses the button, the isCollapsedUpload turns to true or vice versa and the icon changes.
From the controller:
$scope.switcher = function (booleanExpr, trueValue, falseValue) {
return booleanExpr ? trueValue : falseValue;
}
$scope.isCollapsedUpload = false;
<button class="btn" ng-click="isCollapsedUpload = !isCollapsedUpload">
<span>Upload file</span>
<i class="{{ switcher( isCollapsedUpload, 'icon-chevron-right', 'icon-chevron-down' )}}"></i>
</button>
I wrote this directive:
feederliteModule.directive('collapseExtend', function() {
return {
restrict: 'E',
scope: { isCollapsed:'#collapseTarget' },
compile: function(element, attrs)
{
var htmlText =
'<button class="btn" ng-click="isCollapsed = !isCollapsed">'+
' <span>'+attrs.label+'</span>'+
' <i class="{{ switcher(isCollapsed, \'icon-chevron-right\', \'icon-chevron-down\' )}}"></i>'+
'</button>';
element.replaceWith(htmlText);
}
}
});
And now I can use it like:
<collapse-extend
collapse-target="isCollapsedUpload"
label="Upload file"
></collapse-extend>
It doesn't work. No icon changes. No errors,
isCollapsedUpload flag doesn't change. It changes only into directive
Did I miss something?
The reason the class doesn't change correctly is because you are not linking the template properly. This is easy to fix if you use the built in functionality:
var feederliteModule = angular.module('feederliteModule', []);
feederliteModule.directive('collapseExtend', [function() {
return {
restrict: 'E',
scope: {
isCollapsed:'=collapseTarget',
label: '#'
},
template: '<button class="btn" ng-click="isCollapsed = !isCollapsed">'+
'<span>{{ label }}</span>'+
'<i ng-class="{ \'icon-chevron-right\': isCollapsed, \'icon-chevron-down\': !isCollapsed }"></i>'+
'</button>'
}
}]);
feederliteModule.controller('test', ['$scope', function($scope) {
$scope.isCollapsedUpload = false;
}]);
To the best of my understanding, by replacing the parent element, you were removing the isolate scope this object was tied to without creating a new one on the button itself.
EDIT: See a complete working fiddle with multiple buttons
I suggest using a service instead of a controller to maintain your model data. This allows you better separation of concerns as your app gets more complex:
var feederliteModule = angular.module('feederliteModule', []);
feederliteModule.service('btnService', function(){
this.isCollapsedUpload = false;
this.isCollapsedSomething = false;
});
feederliteModule.controller('btnController', function($scope, btnService){
$scope.isCollapsedUpload = btnService.isCollapsedUpload;
$scope.isCollapsedSomething = btnService.isCollapsedSomething;
});
feederliteModule.directive('collapseExtend', function() {
return {
restrict: 'E',
scope: {
isCollapsed:'=collapseTarget',
label:'#'
},
replace: true,
link: function (scope, element, attrs){
scope.switcher = function (booleanExpr, trueValue, falseValue) {
return booleanExpr ? trueValue : falseValue;
};
scope.toggleCollapse = function() {
scope.isCollapsed = !scope.isCollapsed;
}
},
template: '<button class="btn" ng-click="toggleCollapse()">'+
'<span>{{label}}</span>'+
'<i ng-class="switcher(isCollapsed, \'icon-chevron-right\', \'icon-chevron-down\')"></i>'+
'</button>'
}
});
Also, notice that you must use '=' instead of '#' in order for isCollapsed to work as you expect. The answer above needs this as well.

Categories

Resources