2017-05-18 56 views
4

我想創建幾個指令來封裝佈局,這樣我就可以從佈局中抽象出來(這是我理解指令的主要目標之一)。阻止指令和表單

所以我想擁有的是這樣的:

<dialog> 
    <dialog-title></dialog-title> 
    <dialog-body></dialog-body> 
    <dialog-footer></dialog-footer> 
</dialog> 

我創建了3個簡單的指令,這個看起來類似這樣

app.directive('dialog',()=>{ 
    return { 
    template: '<div class="dialog" ng-transclude></div>', 
    replace: true, 
    transclude: true, 
    restrict: 'E', 
    } 
}) 

然後我想,以確保模型定義在一個指令(dialog-body)中將在另一個(dialog-footer)中可見,因爲我需要該對話框上的某種形式以及頁腳中的某些導航按鈕,可能會在不依賴於該形式有效或無效的情況下禁用該按鈕。

<body ng-controller="MainCtrl"> 
    <p>age: {{age}}</p> 
    <dialog> 
     <p>age: {{age}}</p> 
     <dialog-body> 
     <form name="dialogForm"> 
      <p>age: {{age}}</p> 
      <input ng-model="age" minlength="3"/> 
     </form> 
     </dialog-body> 
     <dialog-footer> 
     <p>age: {{age}}</p> 
     </dialog-footer> 
    </dialog> 
    </body> 

在​​ng-model將創建對話框體的範圍年齡變量,但它不會出現在其他指令,直到我把它放在對象和MainCtrl申報。這是它如何工作的:

<body ng-controller="MainCtrl"> 
    <p>age: {{user.age}}</p> 
    <dialog> 
     <p>age: {{user.age}}</p> 
     <dialog-body> 
     <form name="dialogForm"> 
      <p>age: {{user.age}}</p> 
      <input ng-model="user.age" minlength="3"/> 
     </form> 
     </dialog-body> 
     <dialog-footer> 
     <p>age: {{user.age}}</p> 
     </dialog-footer> 
    </dialog> 
    </body> 

和控制器:

app.controller('MainCtrl', function($scope) { 
    $scope.user = {age: 1} 
}) 

現在,我想提出一個形式​​。那應該在對話框體的範圍上創建FormController,就像ng-model那樣(或者這裏有一些區別?)。我需要通過dialog-footer訪問它來檢查表單的有效性。

所以在模板中創建表單後,我需要在MainCtrl的範圍中定義formController,這裏是第一個問題 - 我如何創建FormController的實例?我認爲應該$scope.dialogForm = {$valid: true}用於測試目的工作,這是我最後的模板:

<body ng-controller="MainCtrl"> 
    <p>age: {{user.age}}</p> 
    <p>validity: {{dialogForm.$valid}}</p> 
    <dialog> 
     <p>age: {{user.age}}</p> 
     <p>validity: {{dialogForm.$valid}}</p> 
     <dialog-body> 
     <form name="dialogForm"> 
      <p>age: {{user.age}}</p> 
      <p>validity: {{dialogForm.$valid}}</p> 
      <input ng-model="user.age" minlength="3"/> 
     </form> 
     </dialog-body> 
     <dialog-footer> 
     <p>age: {{user.age}}</p> 
     <p>validity: {{dialogForm.$valid}}</p> 
     </dialog-footer> 
    </dialog> 
    </body> 

這裏談到的主要問題。當​​中的表單有效性發生變化時,它並不反映在其他指令中。爲什麼?我在這裏錯過了什麼?

我的主要目標是在應用程序中爲大多數使用的組件提供指令,以便從實際佈局中抽象出 - 可以以不同的方式完成此操作嗎?

這裏是plunk

回答

3

當對話體的形式有效性的變化不會在其他指令體現。爲什麼?

在你的指令transclude: true將創建一個新的範圍,從父scope在這種情況下是MainCtrl範圍繼承。據我所知,當你聲明<form name="dialogForm">時,angular會綁定一個formController到dialogBody的transcluded範圍,即dialogBody它會做$scope.dialogForm = formController,並且因爲它是一個新的作用域,所以其他transcluded作用域將不會看到此更改。

要解決這個問題,您可以在父範圍中聲明一個共享變量,或者使用controller as語法,它本質上是一回事。

<body ng-controller="MainCtrl as vm"> 

,然後綁定形式vm

<form name="vm.dialogForm"> 
     <p>age: {{vm.user.age}}</p> 
     <p>validity: {{vm.dialogForm.$valid}}</p> 
     <input ng-model="vm.user.age" minlength="3"/> 
    </form> 

plunker

爲什麼這項工作?由於所有新的transcluded作用域都繼承了父作用域中的vm,並且formController vm.dialogForm已綁定到此公共變量,因此所有transcluded作用域都會看到此更改。