使用angularjs中的指令进行模板化

时间:2014-05-19 17:44:36

标签: javascript angularjs angularjs-directive

我试图找出在angularjs中使用指令的位置和方法。我有几个页面有很多输入字段,每次我想添加一些条件ng-class和一个只在某些条件下显示的按钮。一个粗略的例子可以在:

JSFiddle without directives

现在我想减少输入并希望指令可以帮助我。以下代码不起作用,但它可能显示我想去的地方:

这就是我要输入我的html的方式:

  <tr>
    <td>First Name:</td>
    <td>
        <dirty-input attr="firstName"/>
    </td>
  </tr>
  <tr>
    <td>Last Name:</td>
    <td>
        <dirty-input attr="lastName"/>
    </td>
  </tr>

所以我尝试使用以下控制器完成此操作:

app.controller('PersonController', function($scope) {
    $scope.person = {firstName: 'John', lastName: 'Doe'};
    $scope.personEdited = {firstName: $scope.person.firstName, lastName: $scope.person.lastName};
    $scope.firstName = {objName: 'person', editedObject: 'personEdited', attrName: 'firstName'};
    $scope.lastName = {objName: 'person', editedObject: 'personEdited', attrName: 'lastName'};
});

和这个指令:

app.directive('dirtyInput', function() {
    return {
        restrict: 'E',
        scope: {
            attr: '=attr',
        },
        template: '<input type="text" ng-model="{{attr.editedObject}}.{{attr.attrName}}"/>'
    };
});

可以在JSFiddle with directives (not working)

看到

显然,这不起作用。我是在尝试做一些不可能的事情,还是我做错了?

2 个答案:

答案 0 :(得分:1)

你非常接近!

需要改变的一些事情:

  1. ngModel上,你必须引用范围内的财产 而不是:ng-model="{{attr.editedObject}}.{{attr.attrName}}
    你应该有:ng-model="attr.editedObject[attr.attrName]
    (这意味着:&#34;绑定到由范围&#39; s attr属性引用的对象的&edit;&#39;属性引用的对象的名为x的属性。其中x是名称等于attr&#39; s&#39; attrName&#39;属性值的属性。&#34;)
    是的,无论如何!

  2. 为了使隔离范围能够访问实际编辑的对象(即personEdited),它需要对它进行引用。有几种方法可以实现这一点,但我认为最简单的方法是在firstnamelastname对象中引用它。例如: -
    而不是:$scope.firstName = {...editedObject: 'personEdited',...}
    使用:$scope.firstName = {...editedObject: $scope.personEdited,...}

  3. 另请参阅此 short demo

答案 1 :(得分:0)

您误解了隔离范围的工作原理。您的指令模板正在尝试访问其隔离范围上的{{attr.editedObject}}.{{attr.attrName}}。我们假设角度将{{attr.editedObject}}.{{attr.attrName}}解析为personEdited.firstName。现在考虑隔离范围,它目前由单个属性attr组成。当您的指令解析personEdited.firstName时,它会查看其隔离范围,并且只能看到attr。因为personEdited未定义,所以没有任何反应。为了使其工作,您必须在隔离范围中包含另一个属性,该属性在控制器范围上分配了personEdited的值。该属性需要命名为personEdited

scope: {
  attr: '=attr',
  personEdited: '=personEdited'
}

然后你需要在你的指令用法中分配它:

<dirty-input attr="firstName" personEdited="personEdited" />

现在,您的隔离范围可以访问personEdited中定义的PersonController对象。希望这会有所帮助。

修改

在考虑了这一点之后,您可能想要在指令中尝试控制器。根据我的猜测,根据您的问题,您真正想要的是访问PersonController的范围。您可以在指令中使用以下语法完成此操作:

myApp.directive('myDirtyInput', function () {
  return {
    restrict: 'E',
    replace: true,
    templateUrl: 'DirtyInput.html',
    controller: '@',
    name: 'ctrl'
  };
});

这里要注意的两件事是控制器属性和名称属性。这些告诉角度js的是我们将允许我们的指令的用户绑定一个控制器供我们使用,它将通过在指令声明中定义ctrl属性来分配。所以在我们的例子中,这将是:

<my-dirty-input ctrl="PersonController"></my-dirty-input>

现在,我们的控制器绑定到我们的指令,我们可以从指令中完全访问我们的控制器范围。我们不必创建隔离范围,我们可以简单地开始访问控制器的属性。

这是一个有关我猜想你想做的事情的例子(根据你发布的小提琴):http://plnkr.co/edit/4AQkCSIJvqsrUOBOqway?p=preview