กล่องโต้ตอบการยืนยันบน ng-click - AngularJS


85

ฉันกำลังพยายามตั้งค่ากล่องโต้ตอบการยืนยันng-clickโดยใช้คำสั่ง angularjs ที่กำหนดเอง:

app.directive('ngConfirmClick', [
    function(){
        return {
            priority: 1,
            terminal: true,
            link: function (scope, element, attr) {
                var msg = attr.ngConfirmClick || "Are you sure?";
                var clickAction = attr.ngClick;
                element.bind('click',function (event) {
                    if ( window.confirm(msg) ) {
                        scope.$eval(clickAction)
                    }
                });
            }
        };
}])

วิธีนี้ใช้งานได้ดี แต่น่าเสียดายที่นิพจน์ภายในแท็กโดยใช้คำสั่งของฉันไม่ได้รับการประเมิน:

<button ng-click="sayHi()" ng-confirm-click="Would you like to say hi?">Say hi to {{ name }}</button>

(ชื่อไม่ได้รับการประเมินในกรณีนี้) ดูเหมือนว่าจะเป็นเพราะพารามิเตอร์เทอร์มินัลของคำสั่งของฉัน คุณมีแนวคิดในการแก้ไขปัญหาหรือไม่?

เพื่อทดสอบรหัสของฉัน: http://plnkr.co/edit/EHmRpfwsgSfEFVMgRLgj?p=preview


ทำไมคุณถึงใช้เทอร์มินัลในกรณีนี้ ดูเหมือนว่ามันจะทำงานได้อย่างสมบูรณ์แบบโดยไม่ต้อง (และคุณก็รู้) ฉันแค่สงสัยว่าทำไมคุณถึงคิดว่ามันจำเป็นในคำสั่งของคุณ
Simon Belanger

@SimonBelanger ด้วย terminal = false แม้ว่าฉันจะคลิกที่ "ยกเลิก" ในกล่องโต้ตอบการยืนยัน แต่ sayHi () จะถูกทริกเกอร์ เป้าหมายของฉันคือไม่เรียก sayHi () หากผู้ใช้คลิกยกเลิก
poiuytrez

คำตอบ:


92

หากคุณไม่รังเกียจที่จะไม่ใช้ng-clickมันก็ใช้ได้ คุณสามารถเปลี่ยนชื่อเป็นอย่างอื่นและยังคงอ่านแอตทริบิวต์ได้ในขณะที่หลีกเลี่ยงไม่ให้ตัวจัดการคลิกถูกทริกเกอร์ปัญหาสองครั้งในขณะนี้

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

ฉันคิดว่าปัญหาคือterminalสั่งให้คำสั่งอื่นไม่ทำงาน การผูกข้อมูลที่มี{{ }}เป็นเพียงนามแฝงสำหรับที่สั่งซึ่งจะถูกยกเลิกโดยสันนิษฐาน ng-bindterminal


13
ข้อมูลโค้ดนี้ใช้ไม่ได้กับ angular เวอร์ชันปัจจุบันอีกต่อไป ขอบเขต. $ eval (.. ) ควรถูกแทนที่ด้วยขอบเขต $ ใช้ (.. )
CoolTapes

โปรดตรวจสอบคำถามนี้เพื่อดูข้อความยืนยัน JS ด้วย E2E-
testing

วิธีนี้ใช้งานได้ แต่จะเกิดอะไรขึ้นหากฉันเลือกช่องทำเครื่องหมายของ Chrome "หลีกเลี่ยงหน้านี้เพื่อสร้างกล่องโต้ตอบเพิ่มเติม" : s
bigpony

58

แนวทางที่ชัดเจน

อัปเดต: คำตอบเก่า (2014)

โดยทั่วไปจะสกัดกั้นng-clickเหตุการณ์แสดงข้อความที่มีอยู่ในng-confirm-click="message"คำสั่งและขอให้ผู้ใช้ยืนยัน หากคลิกยืนยันการng-clickดำเนินการตามปกติหากไม่ใช่สคริปต์จะยุติและng-clickไม่ทำงาน

<!-- index.html -->
<button ng-click="publish()" ng-confirm-click="You are about to overwrite your PUBLISHED content!! Are you SURE you want to publish?">
  Publish
</button>
// /app/directives/ng-confirm-click.js
Directives.directive('ngConfirmClick', [
  function(){
    return {
      priority: -1,
      restrict: 'A',
      link: function(scope, element, attrs){
        element.bind('click', function(e){
          var message = attrs.ngConfirmClick;
          // confirm() requires jQuery
          if(message && !confirm(message)){
            e.stopImmediatePropagation();
            e.preventDefault();
          }
        });
      }
    }
  }
]);

เครดิตรหัสสำหรับ Zach Snow: http://zachsnow.com/#!/blog/2013/confirming-ng-click/

อัปเดต: คำตอบใหม่ (2016)

1) เปลี่ยนคำนำหน้าจาก 'ng' เป็น 'mw' เหมือนเดิม ('ng') สงวนไว้สำหรับคำสั่งเชิงมุมดั้งเดิม

2) แก้ไขคำสั่งเพื่อส่งผ่านฟังก์ชันและข้อความแทนการสกัดกั้นเหตุการณ์ ng-click

3) เพิ่มค่าเริ่มต้น "แน่ใจหรือ" ในกรณีที่ไม่ได้ระบุข้อความที่กำหนดเองให้กับ mw-confirm-click-message = ""

<!-- index.html -->
<button mw-confirm-click="publish()" mw-confirm-click-message="You are about to overwrite your PUBLISHED content!! Are you SURE you want to publish?">
  Publish
</button>
// /app/directives/mw-confirm-click.js
"use strict";

var module = angular.module( "myApp" );
module.directive( "mwConfirmClick", [
  function( ) {
    return {
      priority: -1,
      restrict: 'A',
      scope: { confirmFunction: "&mwConfirmClick" },
      link: function( scope, element, attrs ){
        element.bind( 'click', function( e ){
          // message defaults to "Are you sure?"
          var message = attrs.mwConfirmClickMessage ? attrs.mwConfirmClickMessage : "Are you sure?";
          // confirm() requires jQuery
          if( confirm( message ) ) {
            scope.confirmFunction();
          }
        });
      }
    }
  }
]);

8
Nb ต้องใช้ jQuery
eggonlegs

1
สิ่งนี้ไม่ได้ผลสำหรับฉัน ไม่มีการยืนยันแสดงและการคลิกดำเนินต่อไป ใครอีกไหม?
OneHoopyFrood

ฉันคิดว่ามันเป็นความคิดที่ดีที่จะไม่เลิกผูกตัวจัดการการคลิก ng-click ก่อนจากนั้นให้หยุดทันทีและป้องกันไม่ให้ค่าเริ่มต้น
James Kleeh

OneHoopyFrood คุณต้องมีฟังก์ชันที่ถูกต้องใน ng-click = "" มิฉะนั้นจะล้มเหลว ขอบคุณ.
mikeborgh

เหตุใดจึงต้องเป็นขั้นตอนที่ 2) แก้ไขคำสั่งเพื่อส่งผ่านฟังก์ชันและข้อความแทนการสกัดกั้นเหตุการณ์ ng-click
เงิน

46

สำหรับฉันhttps://www.w3schools.com/js/js_popup.aspกล่องโต้ตอบการยืนยันเริ่มต้นของเบราว์เซอร์ทำงานได้ดีมาก เพิ่งลองสิ่งนี้:

$scope.delete = function() {
    if (confirm("sure to delete")) {
        // todo code for deletion
    }
};

เรียบง่าย .. :)
แต่ฉันคิดว่าคุณไม่สามารถปรับแต่งได้ จะปรากฏพร้อมกับปุ่ม "ยกเลิก" หรือ "ตกลง"

แก้ไข:

ในกรณีที่คุณใช้ไอออนิกเฟรมเวิร์กคุณต้องใช้ไดอะล็อก ionicPopup ดังใน:

// A confirm dialog


$scope.showConfirm = function() {
   var confirmPopup = $ionicPopup.confirm({
     title: 'Delete',
     template: 'Are you sure you want to delete this item?'
   });

   confirmPopup.then(function(res) {
     if(res) {
       // Code to be executed on pressing ok or positive response
       // Something like remove item from list
     } else {
       // Code to be executed on pressing cancel or negative response
     }
   });
 };

สำหรับรายละเอียดเพิ่มเติมโปรดดูที่: $ ionicPopup


มันดูสะอาด แต่ฉันคิดว่ามันขัดกับวิธีการประกาศใน Angular ง่ายต่อการใส่ตรรกะมุมมองภายในคอนโทรลเลอร์ด้วยวิธีนี้ หากทำได้การทำให้คอนโทรลเลอร์สะอาดจากองค์ประกอบ UI จะเป็นประโยชน์
Jim Aho

1
คุณสามารถกำจัด== trueซึ่งไม่จำเป็นอย่างสมบูรณ์ในกรณีนี้เนื่องจากconfirm()ส่งคืนบูลีนแล้ว ไม่จำเป็นต้องให้ JS พิมพ์บีบบังคับและเปรียบเทียบกับจริง
Léo Lam

10

มันง่ายมากโดยใช้ core javascript + angular js:

$scope.delete = function(id) 
    { 
       if (confirm("Are you sure?"))
           {
                //do your process of delete using angular js.
           }
   }

หากคุณคลิกตกลงการดำเนินการลบจะใช้เวลามิฉะนั้นจะไม่ดำเนินการ * id คือพารามิเตอร์บันทึกที่คุณต้องการลบ


5

คุณไม่ต้องการใช้terminal: falseเนื่องจากนั่นคือสิ่งที่ขัดขวางการประมวลผลภายในปุ่ม แทนการlinkล้างattr.ngClickเพื่อป้องกันพฤติกรรมเริ่มต้น

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

app.directive('ngConfirmClick', [
  function() {
    return {
      priority: 1,
      link: function(scope, element, attr) {
        var msg = attr.ngConfirmClick || "Are you sure?";
        var clickAction = attr.ngClick;
        attr.ngClick = "";
        element.bind('click', function(event) {
          if (window.confirm(msg)) {
            scope.$eval(clickAction)
          }
        });
      }
    };
  }
]);

ใช้งานได้ใน Angular เวอร์ชันที่คุณอ้างอิงใน plunker แต่ถ้าคุณอ้างอิง ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js จะไม่ทำงานตามที่คาดไว้
ChrisW

วิธีที่แนะนำของฉัน Ultimatelly ใช้ได้ผลกับบางกรณีเท่านั้นเนื่องจาก ngClick ทำมากกว่าการผูกแบบง่าย ๆ กับ 'คลิก' ฉันคิดว่าแนวทางที่ถูกต้องกว่าคือการจัดการกับการยืนยันในตัวจัดการ ng-click แทนที่จะใช้แอตทริบิวต์แยกต่างหาก
Stepan Riha

4

ในวันนี้โซลูชันนี้ใช้ได้กับฉัน:

/**
 * A generic confirmation for risky actions.
 * Usage: Add attributes: ng-really-message="Are you sure"? ng-really-click="takeAction()" function
 */
angular.module('app').directive('ngReallyClick', [function() {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            element.bind('click', function() {
                var message = attrs.ngReallyMessage;
                if (message && confirm(message)) {
                    scope.$apply(attrs.ngReallyClick);
                }
            });
        }
    }
}]);

เครดิต: https://gist.github.com/asafge/7430497#file-ng-really-js



4

โซลูชันเชิงมุมอย่างเดียวที่ทำงานควบคู่ng-clickไปได้โดยใช้คอมไพล์เพื่อตัดng-clickนิพจน์

คำสั่ง:

.directive('confirmClick', function ($window) {
  var i = 0;
  return {
    restrict: 'A',
    priority:  1,
    compile: function (tElem, tAttrs) {
      var fn = '$$confirmClick' + i++,
          _ngClick = tAttrs.ngClick;
      tAttrs.ngClick = fn + '($event)';

      return function (scope, elem, attrs) {
        var confirmMsg = attrs.confirmClick || 'Are you sure?';

        scope[fn] = function (event) {
          if($window.confirm(confirmMsg)) {
            scope.$eval(_ngClick, {$event: event});
          }
        };
      };
    }
  };
});

HTML:

<a ng-click="doSomething()" confirm-click="Are you sure you wish to proceed?"></a>

3
    $scope.MyUpdateFunction = function () {
        var retVal = confirm("Do you want to save changes?");
        if (retVal == true) {
            $http.put('url', myData).
            success(function (data, status, headers, config) {
                alert('Saved');
            }).error(function (data, status, headers, config) {
                alert('Error while updating');
            });
            return true;
        } else {
            return false;
        }
    }

โค้ดบอกทุกอย่าง


1

ตัวอย่างโค้ด HTML 5

<button href="#" ng-click="shoutOut()" confirmation-needed="Do you really want to
shout?">Click!</button>

ตัวอย่างโค้ดคำสั่ง AngularJs ที่กำหนดเอง

var app = angular.module('mobileApp', ['ngGrid']);
app.directive('confirmationNeeded', function () {
    return {
    link: function (scope, element, attr) {
      var msg = attr.confirmationNeeded || "Are you sure?";
      var clickAction = attr.ngClick;
      element.bind('click',function (e) {
        scope.$eval(clickAction) if window.confirm(msg)
        e.stopImmediatePropagation();
        e.preventDefault();
       });
     }
    };
});

1

กล่องโต้ตอบการยืนยันสามารถใช้งานได้โดยใช้AngularJS Material :

$ mdDialog เปิดกล่องโต้ตอบบนแอปเพื่อแจ้งให้ผู้ใช้ทราบเกี่ยวกับข้อมูลสำคัญหรือกำหนดให้พวกเขาตัดสินใจ มีสองวิธีในการตั้งค่า: API สัญญาแบบง่ายและไวยากรณ์ของออบเจ็กต์ปกติ

ตัวอย่างการนำไปใช้: Angular Material - Dialogs


0

หากคุณใช้ ui-router ปุ่มยกเลิกหรือยอมรับจะแทนที่ url เพื่อป้องกันสิ่งนี้คุณสามารถส่งคืนเท็จในแต่ละกรณีของประโยคเงื่อนไขเช่นนี้:

app.directive('confirmationNeeded', function () {
  return {
    link: function (scope, element, attr) {
      var msg = attr.confirmationNeeded || "Are you sure?";
      var clickAction = attr.confirmedClick;
      element.bind('click',function (event) {
      if ( window.confirm(msg) )
        scope.$eval(clickAction);
      return false;
    });
  }
}; });

0

วิธีแก้ปัญหาเชิงมุมที่ง่ายมาก

คุณสามารถใช้ id กับข้อความหรือไม่ก็ได้ หากไม่มีข้อความข้อความเริ่มต้นจะแสดงขึ้น

คำสั่ง

app.directive('ngConfirmMessage', [function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            element.on('click', function (e) {
                var message = attrs.ngConfirmMessage || "Are you sure ?";
                if (!confirm(message)) {
                    e.stopImmediatePropagation();
                }
            });
        }
    }
}]);

ตัวควบคุม

$scope.sayHello = function(){
    alert("hello")
}

HTML

พร้อมข้อความ

<span ng-click="sayHello()" ng-confirm-message="Do you want to say Hello ?" >Say Hello!</span>

โดยไม่ต้องยุ่ง

<span ng-click="sayHello()" ng-confirm-message>Say Hello!</span>

0

นี่คือทางออกที่สะอาดและเรียบง่ายโดยใช้สัญญาเชิงมุม$q, $windowและพื้นเมือง.confirm()กิริยา:

angular.module('myApp',[])
  .controller('classicController', ( $q, $window ) => {
    this.deleteStuff = ( id ) => {
      $q.when($window.confirm('Are you sure ?'))
        .then(( confirm ) => {
          if ( confirm ) {
            // delete stuff
          }
        });
    };
  });

ที่นี่ฉันใช้controllerAsไวยากรณ์และฟังก์ชันลูกศร ES6 แต่มันยังใช้งานได้ใน ES5 ธรรมดา


0

ลบป๊อปอัปการยืนยันโดยใช้ bootstrap ใน angularjs

ง่ายมาก .. ฉันมีวิธีแก้ปัญหานี้โดยใช้ป๊อปอัปโครงสร้าง bootstrap ที่นี่ฉันจัดให้

<button ng-click="deletepopup($index)">Delete</button>

ในป๊อปอัปรุ่น bootstrap:

<div class="modal-footer">
  <a href="" data-dismiss="modal" ng-click="deleteData()">Yes</a>
  <a href="" data-dismiss="modal">No</a>
</div>

js

var index=0;
$scope.deleteData=function(){
    $scope.model.contacts.splice(index,1);
}
// delete a row 
$scope.deletepopup = function ($index) {
    index=$index;
    $('#myModal').modal('show');
};

เมื่อฉันคลิกปุ่มลบ bootstrap ป๊อปอัปการลบโครงสร้างจะเปิดขึ้นและเมื่อฉันคลิกใช่แถวปุ่มจะถูกลบ


0

ng-click return ยืนยันว่าใช้งานได้ 100%

ในไฟล์ html เรียกใช้ฟังก์ชัน delete_plot ()

<i class="fa fa-trash delete-plot" ng-click="delete_plot()"></i> 
 
  

เพิ่มสิ่งนี้ลงในคอนโทรลเลอร์ของคุณ

    $scope.delete_plot = function(){
        check = confirm("Are you sure to delete this plot?")
        if(check){
            console.log("yes, OK pressed")
        }else{
            console.log("No, cancel pressed")

        }
    }

-1

ฉันหวังว่า AngularJS จะมีกล่องโต้ตอบการยืนยันในตัว บ่อยครั้งการมีกล่องโต้ตอบแบบกำหนดเองจะดีกว่าการใช้เบราว์เซอร์ในตัว

ฉันใช้ twitter bootstrap เป็นเวลาสั้น ๆ จนกระทั่งมันถูกยกเลิกในเวอร์ชัน 6 ฉันมองหาทางเลือกอื่น แต่สิ่งที่ฉันพบนั้นซับซ้อน ฉันตัดสินใจลองใช้ JQuery UI

นี่คือตัวอย่างของฉันที่ฉันโทรหาเมื่อฉันกำลังจะลบบางสิ่งออกจาก ng-grid

    // Define the Dialog and its properties.
    $("<div>Are you sure?</div>").dialog({
        resizable: false,
        modal: true,
        title: "Modal",
        height: 150,
        width: 400,
        buttons: {
            "Yes": function () {
                $(this).dialog('close');
                //proceed with delete...
                /*commented out but left in to show how I am using it in angular
                var index = $scope.myData.indexOf(row.entity);

                $http['delete']('/EPContacts.svc/json/' + $scope.myData[row.rowIndex].RecordID).success(function () { console.log("groovy baby"); });

                $scope.gridOptions.selectItem(index, false);
                $scope.myData.splice(index, 1);
                */
            },
            "No": function () {
                $(this).dialog('close');
                return;
            }
        }
    });

ฉันหวังว่านี่จะช่วยใครบางคนได้ ฉันดึงผมออกเมื่อต้องการอัพเกรด ui-bootstrap-tpls.js แต่มันทำให้กล่องโต้ตอบที่มีอยู่ของฉันพัง เมื่อเช้านี้ฉันเข้ามาทำงานลองทำบางอย่างแล้วก็รู้ว่าฉันมีความซับซ้อนมากเกินไป

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.