在AngularJS中创建可重用组件

时间:2014-09-10 19:03:41

标签: angularjs

我是Stackoverflow的新手。我也是AngularJS的新手。如果我没有正确使用它,我道歉。不过,我正在尝试使用AngularJS创建UI控件。我的UI控件将如下所示:

+---------------------+
|                     |
+---------------------+

烨。文本框,具有特殊功能。我打算把它放在带按钮的页面上。我的想法是作为开发人员,我想输入这样的东西:

<ul class="list-inline" ng-controller="entryController">
  <li><my-text-box data="enteredData" /></li>
  <li><button class="btn btn-info" ng-click="enterClick();">Enter</button></li>
</ul>

请注意,我想要我控制中的按钮。我还希望enteredData在与子控件关联的范围内可用。换句话说,当调用enterClick时,我希望能够通过$scope.enteredData读取值。为了创建my-text-box,我构建了以下指令:

myApp.directive('myTextBox', [function() {
    return {
        restrict:'E',
        scope: {
          entered: '='
        },
        templateUrl: '/templates/myTextBox.html'
    };
}]);

myApp.controller('myTextBoxController', ['$scope', function($scope) {
    $scope.doSomething = function($item) {
        $scope.entered = $item.name;

        // Need to somehow call to parent scope here.
    };  
}]);

myTextBox.html

<div ng-controller="myTextBoxController">
    <input type="text" class="form-control" ng-model="query" placeholder="Please enter..."  />
</div>

entryController.js

myApp.controller('entryController', ['$scope', function($scope) {
  $scope.enteredData = '';
  $scope.enterClick = function() {
    alert($scope.enteredData);
  };
});

现在,我有两个问题。

  1. 当调用enterClick中的entryController时,$scope.enteredData为空。
  2. 当调用doSomething中的myTextBoxController时,我不知道如何与entryController通信发生了什么事。
  3. 我觉得我已经正确设置了我的指令。我不确定我做错了什么。有人可以指出我正确的方向。

2 个答案:

答案 0 :(得分:1)

给你三个建议。

1)您真的不应该使用引用其他地方定义的控制器的模板来创建指令。它使得该指令不可能单独进行测试,并且通常不清楚。如果需要将数据传递到父作用域的指令中,请使用指令中的isolate作用域对象绑定到该数据(注意指令模板没有控制器)http://jsfiddle.net/p4ztunko/

myApp.directive('myTextBox', [function () {
    return {
        restrict: 'E',
        scope: {
            data: '='
        },
        template: '<input type="text" class="form-control" ng-model="data" placeholder="Please enter..."  />'
    };
}]);

myApp.controller('entryController', ['$scope', function ($scope) {
    $scope.enteredData = 'Stuff';
    $scope.enterClick = function () {
        alert($scope.enteredData);
    };
}]);

<div>
    <ul class="list-inline" ng-controller="entryController">
        <li>{{enteredData}}
            <my-text-box data="enteredData" />
        </li>
        <li>
            <button class="btn btn-info" ng-click="enterClick();">Enter</button>
        </li>
    </ul>
</div>

2)当您不需要时,不要混淆HTML。 angular的目标之一是使标记更具可读性,而不是用随机自定义元素替换标准元素。例如。如果你想观察输入的值并采取行动,取决于你可以在链接功能中做什么(注意:仍然没有引用外部控制器)http://jsfiddle.net/Lkz8c5jo/

myApp.directive('myTextBox', function () {
    return {
        restrict: 'A',
        link: function(scope, element, attrs){
           function doSomething (val) {
              alert('you typed ' + val);
           }
           scope.$watch(attrs.ngModel, function (val) {
               if(val == 'hello'){
                   doSomething(val);
               }
           });
        }
    };
});

myApp.controller('entryController', ['$scope', function ($scope) {
    $scope.enteredData = 'Stuff';
    $scope.enterClick = function (data) {
        alert('You clicked ' + data);
    };
}]);

<div>
    <ul class="list-inline" ng-controller="entryController">
        <li>{{enteredData}}
            <input type="text" ng-model="enteredData" my-text-box />
        </li>
        <li>
            <button class="btn btn-info" ng-click="enterClick(enteredData)">Enter</button>
        </li>
    </ul>
</div>

3)从UI传递数据到控制器函数,而不是在函数中引用$ scope对象,如ng-click =“enterClick(enteredData)”它使测试更容易,因为你从该方法中删除了$ scope依赖项< / p>

答案 1 :(得分:0)

$ scope.enteredData为空,因为您没有使用正确的范围。 entryController中的$ scope与myTextBoxController中的$ scope不同。您需要在指令上指定其中一个控制器,然后使用它来引用适当的范围。

您似乎应该将enterClick和相应的按钮移动到指令模板中。然后将enter单击移动到文本框控制器中,您就可以引用$ scope.enteredData。

您可以使用$ emit通知更改的父作用域。 (这是参考你的评论“//需要以某种方式调用父范围。”)

此外,您可能遇到不使用正确变量的问题。在myTextBox指令中,您声明$ scope.entered,但您实际上是将$ scope.data设置为等于html中的enteredData的值。