2013-06-17 5 views
7

Так что я пытаюсь реализовать пользовательский флажок подтверждения с помощью Angular. В идеале я просто хотел бы добавить атрибут, чтобы включить функциональность. Пример:angularjs custom confirm box

<button type="button" ng-click="delete(foo)">Delete</button> -> <button type="button" ng-click="delete(foo)" ng-confirm="Are you sure you want to delete this foo?">Delete</button> 

(Foo находится внутри нг-повтора ... Foo в fooList ..)

Таким образом, все проблемы, которые я имею вращаться вокруг связывая событие щелчка, что обычно случается с другой кнопка. У меня есть отдельная директива «confirmBox», которая создаст мою модальную (не используя загрузку) и обработает все показания/скрытие/etc.

То, что я в настоящее время использую требует от меня, чтобы изменить мою функциональность нг-клик, которую я действительно хочу, чтобы уйти от:

Текущая реализация:

<button ... ng-click="confirm('Are you sure you want to delete this foo?, 'delete', foo)">Delete</button> 

var confirmModule = angular.module('confirm', []); 

confirmModule.run(function($rootScope) { 
    $rootScope.confirm = function(text, func, obj) { 
     $rootScope.$broadcast('confirm', func, obj, text); 
    }; 
}); 

confirmModule.directive('confirmBox', function($parse) { 

    return { 
     restrict: 'A', 
     template: myModalTemplate, 
     link: function(scope, element, attrs){ 
      element.hide(); 
      var noBtn = element.find("[name='no']"); 
      noBtn.bind("click", function() { 
       element.hide(); 
      }); 
      scope.$on("confirm", function(event, func, obj, text) { 
       var yesBtn = element.find("[name='yes']"); 
       element.show(); 
       yesBtn.unbind("click").bind("click", function() { 
        scope[func](obj); 
       }); 
      }); 
     } 
    } 
}); 

Кто-нибудь есть какие-нибудь идеи? Я начал с добавления директивы для кнопки, а затем открепления события клика, так что ng-click не срабатывает. Затем я остаюсь со строкой 'delete(foo)' из атрибута ng-click, который можно выполнить с помощью $parse(attrs.ngClick)(scope), но я не знаю, как связать это с нажатием кнопки отдельных директив.

Редактировать: Вот скрипка с моей текущей попыткой реализации. Проблема заключается в том, что переменная, передаваемая функции, всегда не определена.

http://jsfiddle.net/UCtbj/2/

Edit2: Обновленные реализации, однако я не особенно нравится, как она связывает две директивы вместе пристреливать другие директивы элементов.

http://jsfiddle.net/UCtbj/3/

ответ

0

Я создал репозиторий для этой функциональности. Он обертывает ui-bootstrap modal для создания окна подтверждения. Он настраивается и легко интегрируется в любое приложение.

Вот ссылка на GitHub: https://github.com/Schlogen/angular-confirm

Пример Usages:

В директиве:

<button type="button" ng-click="delete()" confirm-if="checked" confirm="Are you sure, {{name}}?">Delete</button> 

В качестве услуги:

$confirm({text: 'Are you sure you want to delete?'}) 
    .then(function() { 
    $scope.deletedConfirm = 'Deleted'; 
    }); 
+0

Этот довольно близкий, но вроде прыжки, потому что он изменяет свиток вместо выполнения наложения. – Demodave

6

Мне кажется, что вы пытаетесь сделать что-то JQuery путь внутри директивы. Однако то, что вы хотите, так же просто, как вставить в UI-Bootstrap директиву для подтверждения действий. http://plnkr.co/edit/JhfAF1?p=preview

+2

Проблема с этим состоит в том, что она требует от вас, чтобы поставить этот диалог код в каждой функции, которую вы хотите, чтобы показать. Это действительно не имеет ничего общего с бизнес-логикой приложения, поэтому imo, этого не должно быть. –

+1

Кажется, что угловой пользовательский интерфейс был реорганизован, и служба диалога $ была удалена, и вы можете использовать функциональность сообщений, как указано в плункере. http://stackoverflow.com/questions/19468127/where-is-dialog-messagebox-in-angular-ui – ScottG

+0

Я мог бы реорганизовать его, чтобы использовать $ modal service в моей подтверждающей директиве. Я все еще не хочу использовать $ modal в моем контроллере - его логика представления так не принадлежит. –

1

Чтобы кнопка разметить как

<button type="button" ng-click="deleteItem(drink)" ng-confirm="Are you sure you want to delete '{{drink.name}}'">Delete</button> 

Вы можете написать директиву,

  • перехватывает событие щелчка перед тем ngClick «s обработчик щелчка можно запустить
  • Открывает (используя $modal, а не удаленный $dialog)
  • close диалогового окна (который считается успешным) запускают функцию, указанную атрибутом ngClick для элемента.

На основе кода на the previous answer, вы можете сделать это следующим образом:

app.directive('ngConfirm', function($modal, $parse) { 
    return { 
    // So the link function is run before ngClick's, which has priority 0 
    priority: -1, 

    link: function(scope, element, attrs) { 
     element.on('click', function(e) { 
     // Don't run ngClick's handler 
     e.stopImmediatePropagation(); 

     $modal.open({ 
      templateUrl: 'ng-confirm-template', 
      controller: 'ngConfirmController', 
      resolve: { 
      message: function() { 
       return attrs.ngConfirm; 
      } 
      } 
     }).result.then(function() { 
      // Pass original click as '$event', just like ngClick 
      $parse(attrs.ngClick)(scope, {$event: e}); 
     }); 
     }); 
    } 
    }; 
}); 

, который нуждается в простой контроллер:

app.controller('ngConfirmController', function($scope, $modalInstance, message) { 
    $scope.message = message; 

    $scope.yes = function() { 
    $modalInstance.close(); 
    }; 

    $scope.no = function() { 
    $modalInstance.dismiss(); 
    }; 
}); 

и шаблон для диалога:

<script type="text/ng-template" id="ng-confirm-template"> 
    <div class="modal-body"> 
    <p>{{message}}</p> 
    </div> 
    <div class="modal-footer"> 
    <button class="btn btn-link pull-left" ng-click="no()">No</button> 
    <button class="btn btn-primary pull-right" ng-click="yes()">Yes</button> 
    </div> 
</script> 

Вы можете видеть это работает http://plnkr.co/edit/Gm9lFsGb099w6kCMQoVY?p=preview

Изменить: изменили plunker ссылка на пример без прокрутки появляется/исчезает на экране диалогового

+0

Эта реализация имеет ту же идею, что и моя, однако я вижу некоторые проблемы с ней - см. Мой ответ. –

+0

@JamesKleeh В чем проблема? –

0

Ok, вот тот, в который я попал,

1) Создание службы для диалогового

app.service('dialogModal', [ 
    '$modal', function($modal) { 
    return function(message, title, okButton, cancelButton) { 

     okButton = okButton === false ? false : (okButton || 'Yes'); 
     cancelButton = cancelButton === false ? false : (cancelButton || 'No'); 

     var modalInstance = $modal.open({   
     templateUrl: '/templates/deletePrompt.html', 
     controller: ModalInstanceCtrl, 
     resolve: { 
      settings: function() { 
      return { 
       modalTitle: title, 
       modalBody: message, 
       okButton: okButton, 
       cancelButton: cancelButton 
      }; 
      } 
     } 
     }); 
     // return the modal instance 
     return modalInstance; 
    } 
    } 
]); 

2) Создание контроллера и передать экземпляр модели в нем

var ModalInstanceCtrl = function ($scope, $modalInstance, settings) { 

    angular.extend($scope, settings); 

    $scope.ok = function() { 
    $modalInstance.close(true); 
    }; 

    $scope.cancel = function() { 
    $modalInstance.dismiss('cancel'); 
    }; 
}; 

3) включил ссылку в заголовок, чтобы взять на себя по умолчанию стиль

<link data-require="[email protected]" data-semver="3.1.1" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" /> 

4) переписал стайлинг в моей CSS

5) Вот мое удаление проворной шаблон

<div id="overlayClearMainDiv" class="dialog-modal"> 
    <div id="overlayClearText"> 
    <span>{{modalBody}}</span> 
    </div> 
    <div id="overlayClearButton"> 
    <button id="overlayClearYesButton" class="confirmButton" type="button" ng-click="ok()" ng-show="okButton">{{okButton}}</button> 
    <button class="confirmButton-white" ng-click="cancel()" ng-show="cancelButton">{{cancelButton}}</button> 
    </div> 
</div> 
3

Первый простой сервис для модальных окон:

app.service('ConfirmService', function($modal) { 
    var service = {}; 
    service.open = function (text, onOk) { 
    var modalInstance = $modal.open({ 
     templateUrl: 'myModalContent.html', 
     controller: 'ModalConfirmCtrl', 
     resolve: { 
     text: function() { 
      return text; 
     } 
     } 
    }); 

    modalInstance.result.then(function (selectedItem) { 
     onOk(); 
    }, function() { 
    }); 
    }; 

    return service; 
}) 

app.controller('ModalConfirmCtrl', function ($scope, $modalInstance, text) { 

    $scope.text = text; 

    $scope.ok = function() { 
    $modalInstance.close(true); 
    }; 

    $scope.cancel = function() { 
    $modalInstance.dismiss('cancel'); 
    }; 
}); 

Тогда простая директива, которая использует его:

app.directive('confirm', function(ConfirmService) { 
    return { 
     restrict: 'A', 
     scope: { 
      eventHandler: '&ngClick' 
     }, 
     link: function(scope, element, attrs){ 
      element.unbind("click"); 
      element.bind("click", function(e) { 
      ConfirmService.open(attrs.confirm, scope.eventHandler); 
      }); 
     } 
    } 
}); 

И здесь U Go:

<button ng-click="test(12)" confirm='Are you sure?'>Button</button> 

http://plnkr.co/edit/LOZOnsVyx3JU5XoKYn74?p=preview

+0

Этот выглядит более чисто, чем мой. Вам еще нужен тест && подтвердить в ng-click? Или это как-то связано? – Demodave

+0

Есть ли способ не использовать ui-bootstrap? – Martian2049

0

Вот быстрый один для вас - http://plnkr.co/edit/YklthDZcknmvMjU5A6pe?p=preview

Так в основном, если вы заинтересованы в показе модального диалога, когда пользователь нажимает на, скажем, кнопка нет никакой необходимости, чтобы сделать это трудно. Все, что вам нужно, это простая директива, которая заключает в себе $modal сервис, найденный в ui-bootstrap.

В моем простом примере я просто передаю строку, представляющую сообщение, а затем определяю атрибут on-confirm, который моя директива вызывает, как только пользователь подтверждает. Вызов самой функции усиливает значение $parse для разрешения выражения и после его разрешения вызывает его с помощью области.

Приятный и понятный и вот как он выглядит.

Посмотреть

<body ng-controller="AppController"> 

    <input type="button" value="Delete" 
      confirm="'Are you sure you want to delete me?'" on-confirm="delete()" /> 



    <script type="text/ng-template" id="modal.html"> 
     <div class="modal-header"> 
      <h3 class="modal-title">Confirm</h3> 
     </div> 
     <div class="modal-body"> 
      <p>The world won't be a better place if you delete me.</p> 
     </div> 
     <div class="modal-footer"> 
      <button class="btn btn-primary" ng-click="ok()">OK</button> 
      <button class="btn btn-warning" ng-click="cancel()">Cancel</button> 
     </div> 
    </script> 

</body> 

Controller/Директива

angular 
    .module('App', ['ui.bootstrap']) 
    .controller('AppController', ['$scope', function($scope){ 
     $scope.delete = function(){ 
      alert('Woho, Im deleted!'); 
     }; 
    }]) 
    .directive('confirm', ['$modal', '$parse', function($modal, $parse){ 
     return { 
      link: function(scope, el, attr){ 
       el.bind('click', function(){ 
       var instance = $modal.open({ 
        templateUrl: 'modal.html', 
        controller: ['$scope', '$modalInstance', modalController] 
       }); 

       instance.result.then(function(){ 
        // close - action! 
        $parse(attr.onConfirm)(scope); 
       },function(){ 
        // dimisss - do nothing 
       }); 
       }); 
      } 
     }; 

     function modalController(modalScope, $modalInstance){ 
      modalScope.ok = function(){ 
       modalInstance.close(); 
      }; 
      modalScope.cancel = function(){ 
       modalInstance.dismiss(); 
      }; 
     } 
    }]); 
1

Вот хорошая директива для этого.Это ngBootbox. Проверьте это.

<button class="btn btn-lg btn-primary" 
     ng-bootbox-title="A cool title!" 
     ng-bootbox-custom-dialog="Some custom text" 
     ng-bootbox-buttons="customDialogButtons" 
     ng-bootbox-class-name="some-class"> 
    Custom dialog 
</button> 

<script> 
    $scope.customDialogButtons = { 
     warning: { 
      label: "Warning!", 
      className: "btn-warning", 
      callback: function() { $scope.addAction('Warning', false); } 
     }, 
     success: { 
      label: "Success!", 
      className: "btn-success", 
      callback: function() { $scope.addAction('Success!', true) } 
     }, 
     danger: { 
      label: "Danger!", 
      className: "btn-danger", 
      callback: function() { $scope.addAction('Danger!', false) } 
     }, 
     main: { 
      label: "Click ME!", 
      className: "btn-primary", 
      callback: function() { $scope.addAction('Main...!', true) } 
     } 
    }; 
    </script> 

Demo

ngBootbox