代码之家  ›  专栏  ›  技术社区  ›  Reyedy iniazz

将ng disabled参数设置为$ionicPopup中的按钮

  •  4
  • Reyedy iniazz  · 技术社区  · 8 年前

    我试图创建一个$ionicPopup,其中一个按钮在特定条件下被禁用(作为函数的返回值,我们调用它 MyFunction() ).我想使用 ng-disabled 为此目的。

    问题是,我不知道如何以编程方式添加属性“ng disabled”。

    到目前为止我所做的尝试:

    • 在创建弹出窗口时添加属性,如 attr:"ng-disabled='myFunction()'"
    • 在创建弹出窗口后添加属性,使用JavaScript=>问题是 setAttribute() 方法是在弹出窗口实际显示之前执行的,因此我需要一种方法来检测弹出窗口何时打开,然后才执行该方法。
    • 在弹出式模板中创建作为html元素的按钮,并且不使用 $ionicPopup.show() 方法 这很有效,但我不满意 因为我不想“重新发明轮子”,也不想为爱奥尼亚框架已经涵盖的按钮重新定义CSS样式。

    My JS函数:

    $scope.displayPopUp=function(){
        var alertPopup = $ionicPopup.show({
            templateUrl: 'sharePopUp.html',
            title: 'Invite a friend',
            cssClass: 'popupShare',
            buttons:[
                {
                    text:'Close',
                    type: 'button-round button-no',
                    onTap: function(){
                            /* Some instructions here */
                        }
                },
                { /* v THIS IS THE BUTTON I WANT TO DISABLE UNDER CERTAIN CONDITIONS v */
                    text:'Share',
                    type: 'button-round button-yes',
                    onTap: function(){
                           /* Some instructions here */
                        }
                }
            ]
        }); 
    
        $(".button-yes")[0].setAttribute("ng-disabled", "MyFunction()"); /* NOT WORKING BECAUSE button-yes IS NOT EXISTING YET */
    }
    
    2 回复  |  直到 8 年前
        1
  •  3
  •   Community Mohan Dere    6 年前

    TL;博士

    $timeout(function () {                              // wait 'till the button exists
      const elem = $('.button-yes')[0];
      elem.setAttribute('ng-disabled', 'MyFunction()'); // set the attribute
      $compile(elem)(angular.element(elem).scope());    // Angular-ify the new attribute
    });
    

    现场演示: working plunk

    介绍

    你所遇到的问题,是一个真实的问题,而且显然已经存在多年了。

    这是 the latest version of the code used by $ionicPopup (上次更新于2015年12月)

    此模板是您的Ionic-1弹出窗口使用的模板(来自上面链接的代码的第一行):

    var POPUP_TPL =
      '<div class="popup-container" ng-class="cssClass">' +
        '<div class="popup">' +
          '<div class="popup-head">' +
            '<h3 class="popup-title" ng-bind-html="title"></h3>' +
            '<h5 class="popup-sub-title" ng-bind-html="subTitle" ng-if="subTitle"></h5>' +
          '</div>' +
          '<div class="popup-body">' +
          '</div>' +
          '<div class="popup-buttons" ng-show="buttons.length">' +
            '<button ng-repeat="button in buttons" ng-click="$buttonTapped(button, $event)" class="button" ng-class="button.type || \'button-default\'" ng-bind-html="button.text"></button>' +
          '</div>' +
        '</div>' +
      '</div>';
    

    有一行我们特别感兴趣:按钮模板:

    <button ng-repeat="button in buttons" ng-click="$buttonTapped(button, $event)" class="button" ng-class="button.type || \'button-default\'" ng-bind-html="button.text"></button>
    

    正如你所见 改变按钮属性的内置方式。

    两种方法

    从这里开始,您有两个修复:

    1. 我们可以为他们在GitHub上的项目做出贡献,实现缺失的功能,为其编写测试,记录它,提交问题、请求,要求发布新版本并使用新版本。

    这是理想的解决方案,因为它可以修复 每个人的 问题 永远 .虽然,这确实需要一些时间。也许我会这么做。尽管你可以自己做,给我贴上标签,我会加上你的公关

    1. 编写一段脏代码,在您的特定情况下修补您的特定问题

    这并不理想,但可以奏效 马上

    我将探索并扩展(quick’n dirty) 选项#2 在下面

    修复程序

    到目前为止,您已经尝试了三件事:

    • 第一个根本不是一件事(尽管如果我们实现它、测试它、记录它并发布它,它可能是)
    • 第三个很难维护(如你所知)

    剩下你提到的第二件事:

    使用JavaScript在创建弹出窗口后添加属性

    问题是 setAttribute() 方法是在弹出窗口实际显示之前执行的,因此我需要一种方法来检测弹出窗口何时打开,然后才执行该方法。

    你说得对,但这只是双重问题的第一部分。

    第1部分:按钮尚未创建

    实际上,你可以把电话推迟到 setAttribute 到稍后显示弹出窗口时。你不想把它拖得比人类能注意到的时间更长,所以你不能合理地拖超过20毫秒。
    弹出窗口准备好后是否会有回调,我们可以使用,但没有。

    总之,我只是在逗你:JavaScript的 “多任务” 在这里发挥作用,你可以推迟 0毫秒 哦!
    本质上,这与JS排队的方式有关。将一段代码的执行延迟0毫秒将使其处于待完成任务队列的末尾 “马上”

    只需使用:

    setTimeout(function () {
      $(".button-yes")[0].setAttribute("ng-disabled", "MyFunction()");
    }, 0); // <-- 0, that's right
    

    你们都准备好了!

    你有一个按钮 ng-disabled 属性确实是 "MyFunction()" .但它什么都没做。。。 到目前为止,您只需要一个HTML元素,该元素的属性对简单的HTML按钮没有任何作用: 有棱角的 还没有深入到你的新DOM中,并将自己钩住。

    第2部分:Angular不知道新属性

    关于这一点,这里有很多要读的内容,但归结起来如下:Angular需要 编写 DOM元素,以便它根据特定角度的属性设置运动中的事物。

    Angular根本没有意识到您的按钮有一个新属性,或者它甚至应该关注它本身。

    要让Angular重新编译组件,可以使用(方便地命名) $compile 服务

    它将需要元素来编译,以及角度 $scope 根据(例如, MyFunction 可能不存在于您的 $rootScope )。

    使用它 一旦 ,例如:

    $compile(/* the button */ elem)(/* the scope */ scope);
    

    假设以下元素是您的按钮:

    const elem = $(".button-yes")[0];
    

    。。。通过其相应的角度装饰元素thingy可以得到其实际范围:

    const scope = angular.element(elem).scope();
    

    因此,基本上:

    const elem = $('.button-yes')[0];
    elem.setAttribute('ng-disabled', 'MyFunction()');
    $compile(elem)(angular.element(elem).scope());
    

    Tadaaa!就是这样!ðŸ‰
    。。。差不多吧。直到有一些用户交互会改变相应的 $范围 ,按钮实际上甚至不显示。

    奖励部分:避免 $scope.$apply() $scope.$digest()

    Angular实际上并不是神奇地捕捉变化的事物,然后把它们全都吹到正确的地方。有时,需要明确告诉它四处看看,看看这些元素是否与它们的 $范围

    更具体地说,任何改变 异步发生 不会自行处理:通常,我指的是AJAX调用和 setTimeout -延迟功能。用于告诉Angular同步范围和元素的方法有 $scope.$apply $scope.$digest 。。。我们应该努力避免它们:)

    再一次,有很多关于这方面的阅读。同时,还有一个角度服务(再次),它可以(从概念上讲,它不是字面实现)将所有异步代码包装到 $范围$应用() --我说的是 $timeout

    使用 $超时 而不是 设置超时 什么时候你会改变那些应该改变你的DOM的事情!

    综上所述:

    $超时(函数(){//等待'直到按钮存在
    常量=$(“.按钮是”)[0];
    元素。setAttribute('ng-disabled','MyFunction()');//设置属性
    $编译(elem)(角度元素(elem))。范围());//角度化新属性
    });
    

    现场演示: 工作冲击力

        2
  •  2
  •   Vikasdeep Singh    8 年前

    我认为在ionic v1中,ionic Framework团队尚未按照( Oct 6, '14 10:49 PM ).我想情况还是一样的。但这方面还有工作要做。

    选项1:

    我从您的问题中了解到,您的主要目的是防止用户单击按钮删除ionicPopup按钮并执行一些指示,直到MyFunction()返回True创建您自己的模板,其中包含您可以完全控制的按钮。以下是代码:

    您可以在onTap中实现这一点:。您可以在此处添加MyFunction()的条件,如下所示:

    JavaScript:

    // Triggered on a button click, or some other target
    $scope.showPopup = function() { 
    
      // Enable/disable text"Share" button based on the condition
      $scope.MyFunction = function() {
        return true;
      };
    
      //custom popup
      var myPopup = $ionicPopup.show({
        templateUrl: 'Share'"popup-template.html",
        typetitle: 'button-round"Invite button-yes'a friend",
        onTapscope: function(e)$scope
     { });
    
      // close popup on Cancel ifbutton (MyFunctionclick
      $scope.closePopup = function()) {
        myPopup.close();
      };
    
    };
    

    HTML:

      /*<button Someclass="button instructionsbutton-dark" hereng-click="showPopup()">
     */     show
        </button>
    
      }<script elseid="popup-template.html" {type="text/ng-template">
        <p>Share button is disabled if condition not /satisfied</don'tp>
     allow the user to<button performclass="button unlessbutton-dark" MyFunctionng-click="closePopup()"> returns 
     true     Cancel
        </button>
        e.preventDefault<button class="button button-dark" ng-disabled="MyFunction(); == true"> 
          }Share
        }</button>
      }</script>
    

    这里的工作示例是工作代码笔片段:

    https://codepen.io/anon/pen/bvXXKG?editors=1011

    选项2:

    删除ionicPopup按钮,并使用可以完全控制它们的按钮创建自己的模板。以下是代码:

    JavaScript:

    // Triggered on a button click, or some other target
    $scope.showPopup = function() {
    
      // Enable/disable "Share" button based on the condition
      $scope.MyFunction = function() {
        return true;
      };
    
      //custom popup
      var myPopup = $ionicPopup.show({
        templateUrl: "popup-template.html",
        title: "Invite a friend",
        scope: $scope
      });
    
      // close popup on Cancel button click
      $scope.closePopup = function() {
        myPopup.close();
      };
    
    };
    

    HTML:

      <button class="button button-dark" ng-click="showPopup()">
          show
        </button>
    
      <script id="popup-template.html" type="text/ng-template">
        <p>Share button is disabled if condition not satisfied</p>
        <button class="button button-dark" ng-click="closePopup()"> 
          Close
        </button>
        <button class="button button-dark" ng-disabled="MyFunction() == true"> 
          Share
        </button>
      </script>
    

    以下是工作代码笔片段:

    https://codepen.io/anon/pen/qYEWmY?editors=1010

    注: 应用您自己的样式/按钮对齐方式等

    我希望这对你有帮助。