Reputation: 171341
I created a confirmationDialogHeader
directive which is used like so:
<ul>
<li ng-repeat="item in items">
{{item}}
<button class="btn btn-mini"
confirmation-dialog-header="Delete Item"
confirmation-dialog-action="deleteItem($index)">
Delete
</button>
</li>
</ul>
When the button is clicked, it is supposed to open a confirmation dialog, and if user confirms, it should call deleteItem($index)
, and close the dialog.
My problem is with the last bit: closing the dialog.
Here is the controller (CoffeeScript):
app.controller 'AppCtrl', ['$scope', '$q', '$timeout', ($scope, $q, $timeout) ->
$scope.items = ['Item 1', 'Item 2']
$scope.deleteItem = (index) ->
deferred = $q.defer()
$timeout ->
$scope.items.splice(index, 1) # All good if this line is removed
deferred.resolve()
, 1000
deferred.promise
]
and here is the directive:
app.directive 'confirmationDialogHeader', ['$compile', '$q', ($compile, $q) ->
restrict: 'A'
scope:
confirmationDialogAction: '@'
controller: ($scope) ->
$scope.onConfirm = ->
$scope.$parent.$eval($scope.confirmationDialogAction).then ->
$scope.confirmationDialog = off # Why this doesn't close the dialog?
link: (scope, element, attrs) ->
$confirmationDialog = $ """
<div modal="confirmationDialog">
<div class="modal-header">
<h4>#{attrs.confirmationDialogHeader}</h4>
</div>
<div class="modal-body">
Are you sure?
</div>
<div class="modal-footer">
<button class="btn" ng-click="confirmationDialog = false">
Cancel
</button>
<button class="btn" ng-click="onConfirm()">
Yes
</button>
</div>
</div>
"""
$(document.body).append($confirmationDialog)
$compile($confirmationDialog)(scope)
$(element).click ->
scope.$apply ->
scope.confirmationDialog = yes
]
As you can see, the dialog is not closed after deleteItem()
finishes and $scope.confirmationDialog = off
is executed.
The interesting part is that, if $scope.items.splice(index, 1)
is wrapped with $timeout
, the dialog is closed properly!
$timeout ->
$scope.items.splice(index, 1)
Why this $timeout
wrapping is necessary here?
Are there any guidelines about when should we wrap code with $timeout
?
Working version of this directive that uses $dialog
.
Upvotes: 2
Views: 2189
Reputation: 11391
Are there any guidelines about when should we wrap code with $timeout?
$timeout is used as a replacement to the native setTimeout. The advantage over the native timeout is that it runs the callback in a try/catch block and any errors occurred will be forwarded to your applications exceptionHandler service.
However from my playing with your demo that is not the issue I am seeing and the code can be simplified.
Update I was hoping to get your specific implementation using modal dialog working, but I didn't have much luck. So implemented it using the $dialog service rather than the modal directive. Maybe it will help - here it is
Also, with your original version I found that the scope was being updated when you clicked yes to close the dialog and it was happening within a digest so it should have fired any watchers and thus close the dialog. In that regard I cannot see a reason why it was not working for whatever reason in my browser it made no difference whether or not timeout was used.
Upvotes: 2