Angular指令 - 如何使用JQuery将ngModel和ngBind添加到自定义指令元素?

时间:2014-06-02 12:31:52

标签: javascript jquery angularjs


[信息]
我想要实现的是实现一些自定义角度指令,这些指令将封装它们工作所需的所有JS。
指令不知道它们将显示什么以及存储来自用户的任何输入值的位置。这些信息将来自指令的属性。
我的指令将使用父范围,并且不会创建自己的范围。

[问题] 由于该指令不知道映射ng-model和ng-bind的$ scope中的位置,我的方法是读取指令的属性,确定ng-model和ng-bing属性应该是什么并设置它们到相应的元素。但这不起作用。我认为这是由于我缺乏知识所以我在这里问 - 如果我的方法还可以吗?是否可以以这种方式设置ngModel和ngBind?我做错了什么?。

[我的指令代码]

var directives = angular.module('test.directives', []);

directives.directive("labeledInput", function() {
return {
    restrict: 'E',
    scope: false,
    template: "<div>" +
                "<span class='label'></span>" +
                "<input class='input' type='text'></input>" +
              "</div>",

    link: function(scope, element) {
        var elementIdentifier = angular.element(element[0]).attr("idntfr");
        var elementClass = angular.element(element[0]).attr("element-class");
        var scopeValueName = angular.element(element[0]).attr("value-name");
        var defaultValue = angular.element(element[0]).attr("default-value");
        var elementLabel = angular.element(element[0]).attr("label");

        scope[scopeValueName] = defaultValue;
        scope[elementIdentifier] = elementLabel;

        $(angular.element(element[0]).children()[0]).attr('id', elementIdentifier);
        $(angular.element(element[0]).children()[0]).addClass(elementClass);
        $(angular.element(element[0]).children().children()[1]).attr('ng-model', scopeValueName);
        $(angular.element(element[0]).children().children()[0]).attr('ng-bind', elementIdentifier);
    }
};
});


[结果] 因此,我在HTML页面中看到ng-model和ng-bind绑定在正确的位置,我有范围[scopeValueName] 范围[elementIdentifier] 在Batarang提供的范围内,但我不会在屏幕上看到它们作为值。

有没有人解决过类似的问题?

谢谢你的时间!

[编辑] 对不起,似乎我的问题不明白我会添加一些细节!

以下是我的指令的HTML用法示例:

<labeled-input
    idntfr='id001'
    element-class='someClass'
    value-name='person_name'
    default-value='default'
    label='Person Name:'
>
</labeled-input> 

我在浏览器中对角度解析我的指令后所做的事情就是:

<div id="effect_dt" class="someClass">
    <span class="label" ng-bind="id001"></span>
    <input class="input" type="text" ng-model="person_name">
</div>

我在控制器范围内的内容是 - $ scope.id001 =&#34;人名:&#34;和$ scope.person_name =默认值。但是,这些值根本不会显示在页面上。

3 个答案:

答案 0 :(得分:1)

如果我理解正确你想要做出类似的事情:

<labeledInput>model-name and/or field name</labeledInput>

并将其转换为:

<div>
    <span class='label' ng-bind="mode-name.field-name"></span>
    <input class='input' type='text'></input>
</div>

你必须在指令中阅读更多关于角度编译的内容,无论如何:

  • 获取对指令原始内容的任何访问权限,例如您需要使用的属性或内部内容转换

  • 访问模板内容(例如,在你的情况下让我们说'span'元素)你必须在编译方法中调用tElement参数,因为它将从模板中保存你的html

这里有一些很好的例子: Angularjs: transclude directive template

所有这些操作,例如添加ng-model属性指令等,你应该在指令编译之前添加,为此你必须使用编译块(代替你的'link()'块):

.compile = function compile(tElement, tAttrs) {
    //here add some code eg append ng-model attribute etc.
    return {
    pre: function preLink(scope, iElement, iAttrs) {},
        post: function postLink(scope, iElement, iAttrs) {}
    }
}

和最后一部分 - 控制器范围,最简单的方法就是在模板中添加控制器,这样你就不会失去任何范围。

编辑:

在阅读了更新后的问题之后,请试一试:p

app.directive('labeledInput', function($compile) {

  var directive = {};
  directive.transclude = true;
  directive.restrict =  'E';
  directive.template =  "<div>" +
                "<span class='label' ></span><br/>" +
                "<input class='input' type='text' ></input>" +
              "</div>";

  directive.compile =  function(cElem, cAttrs) {
    var scope=angular.element(cElem).scope();

    console.log(scope);

    var elementIdentifier = angular.element(cElem[0]).attr("idntfr");
    var elementClass = angular.element(cElem[0]).attr("element-class");
    var scopeValueName = angular.element(cElem[0]).attr("value-name");
    var defaultValue = angular.element(cElem[0]).attr("default-value");
    var elementLabel = angular.element(cElem[0]).attr("label");

     $(cElem[0]).find("div").attr('id', elementIdentifier).addClass(elementClass);

     $(cElem[0]).find("div span").attr('ng-bind', scopeValueName);
     $(cElem[0]).find("div input").attr('ng-model', elementIdentifier);
     return {
            pre: function preLink(scope, iElement, iAttrs) {
            scope[scopeValueName] = defaultValue;
      scope[elementIdentifier] = elementLabel;

            }
     };
    };

  return directive;
});

<击> http://plnkr.co/edit/ImJmTHP3eQCzPaKfRTS4?p=preview

http://plnkr.co/edit/KIcfwsUGfCeg1UtioFv0?p=preview

答案 1 :(得分:0)

我不确定是否正确,但我想你想构建某种泛型指令,其行为来自父作用域并绑定到它的模板,在本例中是输入字段。

您可以在labeledInput指令上创建一个隔离范围,如下所示:

scope: {
   doSomething:'&' 
}

它的模板将成为: -

template: "<div>" +
            "<span class='label'></span>" +
            "<input class='input' type='text' ng-change="doSomething()"></input>" +
          "</div>",

你的HTML将是: -

    <labeledInput doSomething="someFunctionOnController()"></labeledInput>

因此,在更改输入字段时将调用控制器范围中定义的someFunctionOnController。

答案 2 :(得分:0)

有一种更简单的方法可以做到这一点:(见http://jsfiddle.net/j55B8/17/处的jsfiddle)

指令代码:

var directives = angular.module('test.directives', []);

directives.directive("labeledInput", function() 
    return {
        restrict : "E",
        replace : true,
        scope : {
            "idntfr" : "@",
            "elementClass" : "@",
            "valueName" : "=",
            "defaultValue": "@",
            "label" : "@"
        },
        template : "<div id='{{idntfr}}' class='{{elementClass}}' ng-init='valueName=defaultValue'>" +  
                       "<span class='label' ng-bind='label'></span>" +
                       "<input class='input' type='text' ng-model='valueName'></input>" +
                   "</div>"
    }
});

HTML

<labeled-input 
    idntfr='id001' 
    element-class='someClass' 
    value-name='person_name' 
    default-value='default name' 
    label='Person Name: '>
</labeled-input>

The value typed in the above text box is {{person_name}}