AngularJS - 指令/范围问题

时间:2014-08-21 03:34:39

标签: jquery angularjs directive

我有一个旧的jQuery插件我写道,我现在希望将类似的功能转移到角度指令。长话短说我希望它将select标签转换为以下HTML。

<div class="a">
  <span class="b" />
  <span class="c">{{text}}</span>
  <select></select> <!-- this is the original select -->
</div>

选择看起来与此相似:

<select data-ng-options="s.SomeValue as s.SomeLabel for s in someScopeArray" 
  data-ng-change="notifyForSomeFun()" data-ng-model="someValue"></select>

我试图使用&#34;链接&#34;在新指令上运行,只需执行相同类型的jQuery包装,然后添加我想要的<select>周围的HTML,就像我在普通的jQuery插件中所做的那样,但是我开始分解的地方需要更新应用于ng-model的{​​{1}},并更新<select>上的{{text}}绑定。

这是我最近的一次拙劣尝试:

<span class="c">

我是第一个承认,当谈到指令时,我的头脑正在爆炸。我知道我在范围方面存在某种问题。当前版本会在var selectWrapperDirective = function () { return { restrict: 'A', scope: true, link: function (scope, element, attrs) { var $this = element; var defaults = { containerClass: 'selectWrapper', labelClass: 'label', dropImageClass: 'dropImage' }; var itemText = function () { return $this.find('option:selected').text(); }; var opts = angular.extend({}, defaults, scope.$eval('{' + attrs.selectWrapper + '}')); var oldNgChange = attrs['ngChange']; var ngModel = attrs['ngModel']; if (ngModel) { console.log('setting new ngmodel'); attrs.$set('ngModel', '$parent.' + ngModel); } // wrap it in a div and add the class, add a span with label class, add a span with dropimage class $this.wrap('<div class="' + opts.containerClass + '" />'); var container = $this.parent(); container.prepend('<span class="' + opts.dropImageClass + '" />'); container.prepend('<span class="' + opts.labelClass + '">' + itemText() + '</span>'); attrs.$set('ngChange', 'onItemChanged()'); scope.onItemChanged = function () { console.log('onItemChanged fired'); $this.closest('div').find('.' + opts.labelClass).text(itemText()); if (oldNgChange) scope.$parent.$eval(oldNgChange); }; } } }; 触发时更新{{text}},但不会更新父级中的模型。我需要在整个页面中使用这个指令多次与一堆不同的模型,所以我认为我需要某种孤立的范围。 HALP!

修改的 我已经接受了Chad Robinson的回答并在那里发表评论。最终他的答案与AngularJS: Dropdown directive with custom ng-options的SO问题/答案配对,这是我解决问题的原因。

onItemChanged

1 个答案:

答案 0 :(得分:2)

有可能完成你的开始,但是你正在跳过很多关于AngularJS的方法。考虑使用<my-select>而不是<select>之类的内容。然后你可以做类似的事情:

var selectWrapperDirective = function () {
    return {
        restrict: 'E',
        replace: true,
        template: '<div class="a"><span class="b" />' +
                  '<span class="c">{{text}}</span>' +
                  '<select></select></div>',
        link: function ($scope, iElement, iattrs) {
            // ...
        }
    };
};

当Angular编译你的指令时,它会插入模板中的所有内容,然后运行你的链接功能。您仍然可以使用最初想要应用于模板内<select>元素的任何/所有属性,并且您仍然可以在事物上注册更改侦听器,尽管您通常会执行<select ng-change="selectionChanged();"></select>之类的操作并定义{链接函数中的{1}} - 它可以直接手动绑定元素更改事件,从而节省了大量工作。

IMO元素指令是AngularJS的三个或四个最大优势之一 - 它们为您提供当今聚合物/ WebComponents所有人正在努力的一切,并且功能非常强大。在这里不使用它们是一种耻辱,因为你的用例只是尖叫着他们的名字......