AngularJS-Directive(隔离范围的问题)

时间:2017-03-27 06:30:48

标签: angularjs angularjs-directive angularjs-scope

我有一个指令,负责确认过程的功能(见图片)。它按预期工作,除非单击“提交”按钮后,将显示所有tr的检查图标。但是,它只应显示在已经确认的tr上。

不幸的是,我无法创建一个有效的Plunker,并希望这些图片足以让您理解我的问题。

我做错了什么?

角指令:

    .directive('confirm', function($timeout) {
      return {
        restrict: 'A',
        scope: true, // isolate the scope to trigger target individually
        link: function(scope, element) {
          $timeout(function() {
            var barIcon = angular.element(element[0].querySelector('.config-menu-bars'));
            var banIcon = angular.element(element[0].querySelector('.config-menu-ban'));
            var checkIcon = angular.element(element[0].querySelector('.config-menu-checked'));
            var confirmLink = angular.element(element[0].querySelector('.confirm'));
            var textArea = angular.element(element[0].querySelector('.confirmation-note'));

            // These elements are outside the scope of the directive
            var confirmBox = angular.element('.accept-terminplanung');
            var submitButton = angular.element('.submit-appointment');
            var confirmCheckbox = angular.element('.appointment');

            // Hide barIcon and show banIcon, textArea and confirmBox
            confirmLink.bind('click', function() {
              barIcon.hide();
              banIcon.show();
              textArea.show();
              confirmBox.show();
            });

            // Hide banIcon, textArea, confirmBox and show barIcon
            banIcon.bind('click', function() {
              banIcon.hide();
              textArea.hide();
              confirmBox.hide();
              barIcon.show();
              confirmCheckbox.parent().removeClass('checked');
              submitButton.addClass("disabled");
            });

            // Hide barIcon, textArea, confirmBox and show checkIcon after clicking the submitButton
            submitButton.bind('click', function() {
              banIcon.hide();
              textArea.hide();
              confirmBox.hide();
              checkIcon.show();
              confirmCheckbox.parent().removeClass('checked');
              submitButton.addClass("disabled");
            });

            // checkbox functionality whithin the confirmBox
            confirmCheckbox.on('ifChecked', function() {
              submitButton.removeClass('disabled');
            });

            confirmCheckbox.on('ifUnchecked', function() {
              submitButton.addClass('disabled');
            });

          });
        }
      }
    });

HTML:

        <table class="table table-hover">
          <thead>
            <tr>
              <th>Ausbildung</th>
              <th>Termine</th>
              <th>Ausbildungsstätte</th>
            </tr>
          </thead>
          <tbody>
            <tr confirm>
              <td>
                <ul class="nav navbar-nav">
                  <li class="dropdown">
                    <a aria-expanded="false" role="button" data-target="#" class="dropdown-toggle config-menu config-menu-bars" data-toggle="dropdown">
                      <i class="fa fa-bars"></i>
                    </a>
                    <a aria-expanded="false" role="button" class="dropdown-toggle config-menu config-menu-ban"  style="display: none;">
                      <i class="fa fa-ban"></i>
                    </a>
                    <a aria-expanded="false" role="button" class="dropdown-toggle config-menu config-menu-checked"  style="display: none;">
                      <i class="fa fa-check-square-o"></i>
                    </a>
                    <ul role="menu" class="dropdown-menu">
                      <li><a class="confirm" data-target="">Bestätigen</a></li>
                      <li><a class="move" data-target="">Verschieben</a></li>
                    </ul>
                  </li>
                </ul>
              </td>
              <td>
                <p><strong>Ausbildungsname</strong></p>
                <p>Kürzel</p>
              </td>
              <td>
                <p><strong class="text-navy">28.05.2016 </strong>| 09:00 - 16:00 Uhr</p>
                <p><strong class="text-navy">29.05.2016 </strong>| 09:00 - 16:00 Uhr</p>
                <p><strong class="text-navy">30.05.2016 </strong>| 09:00 - 16:00 Uhr</p>
              </td>
              <td>
                <p><strong>Ausbildungsstätte Wunderfull ABC</strong></p>
                <p>Musterstraße 1, 1234 Musterstadt</p>
                <p><i class="fa fa-th-large"></i></span> Seminarraum, Kursraum, Fitnessfläche</p>
              </td>
            </tr>
            <tr confirm>
              <td>
                <ul class="nav navbar-nav">
                  <li class="dropdown">
                    <a aria-expanded="false" role="button" data-target="#" class="dropdown-toggle config-menu config-menu-bars" data-toggle="dropdown">
                      <i class="fa fa-bars"></i>
                    </a>
                    <a aria-expanded="false" role="button" class="dropdown-toggle config-menu config-menu-ban"  style="display: none;">
                      <i class="fa fa-ban"></i>
                    </a>
                    <a aria-expanded="false" role="button" class="dropdown-toggle config-menu config-menu-checked"  style="display: none;">
                      <i class="fa fa-check-square-o"></i>
                    </a>
                    <ul role="menu" class="dropdown-menu">
                      <li><a class="confirm" data-target="">Bestätigen</a></li>
                      <li><a class="move" data-target="">Verschieben</a></li>
                    </ul>
                  </li>
                </ul>
              </td>
              <td>
                <p><strong>Ausbildungsname</strong></p>
                <p>Kürzel</p>
              </td>
              <td>
                <p><strong class="text-navy">28.05.2016 </strong>| 09:00 - 16:00 Uhr</p>
                <p><strong class="text-navy">29.05.2016 </strong>| 09:00 - 16:00 Uhr</p>
              </td>
              <td>
                <p><strong>Ausbildungsstätte Wunderfull ABC</strong></p>
                <p>Musterstraße 1, 1234 Musterstadt</p>
                <p><i class="fa fa-th-large"></i></span> Seminarraum, Kursraum, Fitnessfläche</p>
              </td>
            </tr>
            <tr confirm>
              <td>
                <ul class="nav navbar-nav">
                  <li class="dropdown">
                    <a aria-expanded="false" role="button" data-target="#" class="dropdown-toggle config-menu config-menu-bars" data-toggle="dropdown">
                      <i class="fa fa-bars"></i>
                    </a>
                    <a aria-expanded="false" role="button" class="dropdown-toggle config-menu config-menu-ban"  style="display: none;">
                      <i class="fa fa-ban"></i>
                    </a>
                    <a aria-expanded="false" role="button" class="dropdown-toggle config-menu config-menu-checked"  style="display: none;">
                      <i class="fa fa-check-square-o"></i>
                    </a>
                    <ul role="menu" class="dropdown-menu">
                      <li><a class="confirm" data-target="">Bestätigen</a></li>
                      <li><a class="move" data-target="">Verschieben</a></li>
                    </ul>
                  </li>
                </ul>
              </td>
              <td>
                <p><strong>Ausbildungsname</strong></p>
                <p>Kürzel</p>
              </td>
              <td>
                <p><strong class="text-navy">28.05.2016 </strong>| 09:00 - 16:00 Uhr</p>
              </td>
              <td>
                <p><strong>Ausbildungsstätte Wunderfull ABC</strong></p>
                <p>Musterstraße 1, 1234 Musterstadt</p>
                <p><i class="fa fa-th-large"></i></span> Seminarraum, Kursraum, Fitnessfläche</p>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
      <div class="panel panel-default confirm-panel accept-terminplanung" confirm>
        <div class="panel-body text-muted ibox-heading">
          <form action="#" method="post" role="form">
            <div class="i-checks" ichecks>
              <label class="">
                <div class="icheckbox_square-green">
                  <input type="checkbox" class="i-checks appointment">
                </div>
                <p class="no-margins">Hiermit  akzeptiere ich  die Bedingungen des geschlossenen Dozentenvertrages und nehme den Bildungsauftrag für die ausgewählten Ausbildungen verbindlich an.</p>
              </label>
            </div>
            <button type="button" name="termin-bestaetigen" class="btn btn-sm btn-w-m btn-warning submit-appointment disabled">Terminplanung übernehmen</button>
          </form>
        </div>
      </div>

图片:

1) enter image description here

2) enter image description here

3) enter image description here

4) enter image description here

5) enter image description here

1 个答案:

答案 0 :(得分:1)

您在指令中使用scope: true。这样做是创建一个从父范围继承的新子范围,这与隔离范围不同。如果您在同一父级别上有多个指令(在您的情况下为confirm),则它们将使用相同的子范围。

要说清楚:使用scope: true将创建一个新的子范围,除非已经存在(例如由另一个指令创建)。所以在你的情况下,所有的确认指令都使用相同的范围。

您应该如何制作隔离范围?

scope: {...}给它一个对象哈希。这将创建一个完全隔离的范围,这将允许指令在相同的范围级别上重用,而不会相互干扰。

您可以在此处找到有关此内容的更多信息:Angular JS Docs - Scope

  

scope属性可以是false,true或对象:

     

false(默认值):不会为该指令创建范围。该指令将使用其父级的范围。

     

true:将为指令的元素创建一个原型继承自其父级的新子范围。如果多个   对同一元素的指令请求一个新范围,只有一个新范围   已创建。

     

{...}(对象哈希):为指令的模板创建一个新的“隔离”范围。 “隔离”范围与正常范围不同   它没有原型继承其父范围。这是   在创建可重用组件时很有用,但不应该   意外地读取或修改父作用域中的数据。注意一个   隔离范围指令没有模板或templateUrl不会   将隔离范围应用于其子元素。

<强>更新

您使用confirm四次,因此它会通过链接功能四次。每次通过链接功能时,您都会将某些功能绑定到页面上的按钮。名为termin-bestaetigen的按钮有四个绑定到它的事件,confirm上的trdiv上的confirm三次。当您单击按钮时,所有这些事件都会触发,而在所有这些事件中,您不会检查任何内容,只是显示/隐藏所有内容。

在这种情况下,我建议您在更多一口大小的块中分解您的指令(至少将trdiv上的confirm分开)并将某些功能指向一个控制器。您可以在true指令中添加一个属性,您可以在指令中查看该属性,并且一旦该属性求值为id,您就可以显示/隐藏任何内容。