簡體   English   中英

編譯動態內容 - AngularJS

[英]Compiling dynamic content - AngularJS

我正在重寫這個問題,因為我認為原文不太清楚。

基本上,我有一個'wrapper'指令,我試圖動態地將屬性添加到一個包裝(transcluded)元素。 我可以讓它工作,但Angular似乎並沒有意識到添加后的新屬性。

如果我使用$compile那么Angular會識別它們 - 但是以雙重編譯被轉換的內容為代價,在這種情況下,它會使select標簽中的options數量加倍。

這里是一個plunker能證明(有注釋)什么,我試圖,下同代碼如下對於那些誰可以查看代碼,並暗示答案只是看:(注意-我的最終目的是檢查自定義指令valid-form-group required屬性的valid-form-group ,如果找到將其應用於包含的select標記)

HTML

<body ng-controller="MainCtrl">

  <form name="validationForm" novalidate>

    <valid-form-group class="form-group" ng-class="{'has-error': validationForm.validInfo.$error.required}" required>

      <select ng-model="data.option" ng-options="option.id as option.message for option in selectOptions" name="validInfo" id="validInfo">
        <option value="">-- Select a Question --</option>
      </select>

    </valid-form-group>

  </form>

</body>

JS

var app = angular.module('plunker', [])
  .controller('MainCtrl', function($scope) {
    $scope.selectOptions = [
      {id: 1, message: 'First option'}, 
      {id: 2, message: 'Second option'}, 
      {id: 3, message: 'Third option'}
    ];
  })
  .directive('validFormGroup', function($compile) {
    return {
      restrict: 'E',
      template: '<div><span ng-transclude></span></div>',
      replace: true,
      transclude: true,
      require: '^form',
      link: function(scope, element, attrs, ctrl) {

        if (attrs.required !== undefined) {

          var selectElement = angular.element(element.find('select'));
          // either of the below produce the same results
          selectElement.attr('ng-required', true);
          //selectElement.attr('required', true);

          // if the below is commented out it wont validate
          // BUT if it is left in it will recompile and add another 3 options
          $compile(selectElement)(scope); 
        }
      }
    };
  });

CSS

.has-error{
  border: solid 1px red;
}

請注意,此處的示例使用“ required ”(或ng-required )作為添加的屬性,以突出顯示Angular無法識別它的事實,除非編譯。

歡迎任何幫助或評論 - 有點失望,我不能讓它工作,所以也許有一些基本的我缺少...

plunker應該有助於可視化我的問題。

編輯 - 對答復和評論的延遲表示歉意。 如下面的評論或兩條評論所述,個人問題使我無法找到時間進行調查。

試試這個簡單的指令:

.directive('validFormGroup', function($compile) {
    return {
        restrict: 'A',
        replace: false,
        require: '^form',
        compile: function (element, attr) {
            if (attr.required !== undefined) {
                var selectElement = element.find('select');
                // either of the below produce the same results
                selectElement.attr('ng-required', true);
                //selectElement.attr('required', true);
            }
        }
    };
});

並將其用作html屬性:

<div valid-form-group class="form-group" ng-class="{'has-error': validationForm.validInfo.$error.required}" required>

      <select ng-model="data.option" 
      ng-options="option.id as option.message for option in selectOptions"
      name="validInfo" id="validInfo" >
<option value="">-- Select a Question --</option>
</select>
      <br/>
      <br/>Required invalid? {{validationForm.validInfo.$error.required||false}}
      <br/>
      <br/>

</div>

DEMO

說明

  • 我在這個解決方案中根本沒有使用transclude ,因為這個指令的目的只是在用范圍編譯之前修改html ,不需要過於復雜的被轉換內容。

  • 這里我處理compile函數而不是link函數。 compile函數是一個很好的地方,你可以在鏈接到范圍之前修改html。

我只能猜測你看到的是在指令初始化過程中雙重編譯的結果,這就是你看到雙組選項的原因。

您可以通過將編譯包裝在$ timeout內來解決此問題,這將確保編譯在指令初始化之外發生。 這是一個工作演示 ,在指令代碼下面:

.directive('validFormGroup', function($compile, $timeout) {
  return {
    restrict: 'E',
    template: '<div><span ng-transclude></span></div>',
    replace: true,
    transclude: true,
    require: '^form',
    link: function(scope, element, attrs, ctrl) {
      if (attrs.required !== undefined) {
        var selectElement = angular.element(element.find('select'));
        $timeout(function(){
          selectElement.attr('ng-required', true);
          $compile(selectElement)(scope);
        });
      }
    }
  };
});      

PS您可以通過在指令上使用隔離范圍,然后檢查您的transcluded輸入/選擇元素是否具有所需的屬性集來實現類似的引導程序包裝器功能。 在隔離范圍上定義一個函數以檢查錯誤,並將此函數綁定到form-group ng-class has-error。 這樣你就不必使用$ timeout了。

我想在這里建議一種不同的方法,我適應了動態驗證。 將動態驗證動態添加到字段中,減少每個字段的樣板html代碼,我已經編寫了一個類似用途的指令。 請參閱示例指令的plunker鏈接... PLUNKER

我已經為所有類型的字段編寫了這樣的指令:數字,文本,選擇,textarea,bool,datepicker等...附帶的plunker為您提供了文本和數字字段的示例。

使用下面的襯墊發生角度的魔力:

  var newElem = angular.element(template);
  element.replaceWith(newElem);
  $compile(newElem)(scope);

所有其他代碼只是一些邏輯if else部分..

在這種情況下,您不需要使用$ compile。 我剛剛更改了代碼來解決您的問題。 我盡量保持與原始版本盡可能接近,以幫助您理解。

Javascript(根據attrs.required添加了isRequired范圍變量)

  .directive('validFormGroup', function($compile) {
    return {
      restrict: 'E',
      template: '<div><span ng-transclude></span></div>',
      replace: true,
      transclude: true,
      require: '^form',
      link: function(scope, element, attrs, ctrl) {
        if (attrs.required !== undefined) {
          //added isRequired
          scope.isRequired = true;

          var selectElement = angular.element(element.find('select'));
          // either of the below produce the same results
          //selectElement.attr('ng-required', true);
          //selectElement.attr('required', true);

          // if the below is commented out it wont validate
          // BUT if it is left in it will recompile and add another 3 options
          //remove $compile
          //$compile(selectElement)(scope); 
        }
      }
    };
  });

HTML(添加了ng-required = isRequired)

<select ng-model="data.option" ng-options="option.id as option.message for option in selectOptions" name="validInfo" id="validInfo" ng-required="isRequired">

你可以參考http://plnkr.co/edit/BGQo05mTNr1H1HjFXSpf?p=preview上的plunkr版本

我想這回答了你的問題。 如果你有更復雜的情況,請分享。

更新:(通讀別人評論並再次回答)如果您需要動態HTML內容,可以使用此解決方案 - 從數據庫編譯動態HTML字符串

另一種方法是刪除ng- *屬性以防止重新編譯。 plunkr版本http://plnkr.co/edit/JpfdvISCZ39heuUfdHt3?p=preview

      selectElement.removeAttr('ng-options');
      selectElement.removeAttr('ng-model');

我沒有一個完整的答案,但是如果你給你的指令一個孤立的范圍范圍:{},那么在雙重編譯它無法獲得選項所以無聲地失敗 - 我在你的plunkr嘗試了這個我只有一個下拉列表中的選項集。

我說我沒有競爭的答案 - 我不相信它 - 它似乎是一個黑客,我認為你需要與指令分享你可能能夠繼承這些內容的范圍通過繼承的范圍,以便您可以維護功能,但正如我說它感覺hacky並感覺不對,因為它沒有解決如何最好地處理雙重編譯的基本問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM