选择Angular指令不会为Controller As触发$ watch

时间:2015-09-23 00:39:21

标签: javascript angularjs

我跟随了来自here的Lukas Rubalke @simpulton的工作,并且发现并阅读了this所以扩展了他的工作。

我已经关注了两个并且显示了选择的选择框。我遇到的问题是我需要调用'selected:updated'来刷新Chosen,以便来自控制器的数据将填充选择选项(数据来自$ promise / web服务)。

我正在使用一个控制器来获取数据并创建5个不同的选择框。 (5种不同的过滤列表)。我正在使用Controller As语法和ui-router。

根据我所说的,我应该按照我所遵循的例子,但

element.trigger('chosen:updated');

永远不会被调用,而选择选择当然不会显示选项。在检查DOM时,选项就在那里,它们是从控制器数据创建的。我只是无法接到“更新”的电话。

这是指令:

angular.module('reporting.directive')

.directive("chosen", function () {

    var linker = function (scope, element, attr) {
        var list = attr['chosen'];

        scope.$watch(list, function () {
            element.trigger('chosen:updated');
        });


        element.chosen({
            single_backstroke_delete: false,
            search_contains: true,
            no_results_text: "Oops, nothing found!",
            width: "100%"
        });
    };

    return {
        restrict: 'A',
        link: linker
    }
})
;

和HTML / Template:

<div class="col-xs-12 col-md-2">
    <div class="filterboxtext">Cost Center</div>
    <select id="costcenter" class="chosen-select" chosen="selectsController.datacostcenter" data-placeholder="ALL" multiple
            ng-model="csSelect1" ng-options="cc2 as cc2 for cc2 in selectsController.datacostcenter"></select>
</div>
<div class="col-xs-12 col-md-2">
    <div class="filterboxtext">Provider Name</div>
    <select id="providername" class="chosen-select" chosen="selectsController.dataprovname" data-placeholder="ALL" multiple ng-change="$state.forceReload()"
            ng-model="csSelect2" ng-options="provname as provname for provname in selectsController.dataprovname"></select>
</div>

<SNIP> 

<div class="col-xs-12 col-md-2">
    <input id="hubmenuitemdescription" value="" />
</div>

修改

这是控制器

angular.module('reporting.controller')

.controller('SelectsController', function (SelectDataRetrival) {
    var selectsController = this;

    selectsController.datacostcenter   = SelectDataRetrival.query({ stuff: stuff });
    selectsController.dataprovname     = SelectDataRetrival.query({ stuff: stuff2 });
})
;

编辑2 我已确认$ watch在$ promise解决之前触发了element.trigger('chosen:updated');。我有范围内的数据var,并且按照我理解的方式引用它。 (下面的更新代码)。

我仍然难以理解为什么在更新optionData时不会调用scope.$watch('selectsController.optionData', ...(就像我认为的那样)。

更新了控制器:

angular.module('reporting.controller')

.controller('SelectsController', function (SelectDataRetrival,$q) {
    var selectsController = this;

    selectsController.optionData = [];

    var datacostcenter   = SelectDataRetrival.query({ stuff: stuff });
    var dataprovname     = SelectDataRetrival.query({ stuff: stuff2 });

    $q.all([datacostcenter.$promise, dataprovname.$promise])
            .then(function (results) {
                for (var i = 0; i < results.length; i++) {
                    selectsController.optionData.push(results[i]);
                }
                console.log("controller finished, data assigned"); 
            });
})
;

更新了HTML:

<div class="col-xs-12 col-md-2">
    <div class="filterboxtext">Cost Center</div>
    <select id="costcenter" class="chosen-select" chosen data-placeholder="ALL" multiple
            ng-model="csSelect1" ng-options="cc2 as cc2 for cc2 in selectsController.optionData[0]"></select>
</div>
<div class="col-xs-12 col-md-2">
    <div class="filterboxtext">Provider Name</div>
    <select id="providername" class="chosen-select" chosen data-placeholder="ALL" multiple ng-change="$state.forceReload()"
            ng-model="csSelect2" ng-options="provname as provname for provname in selectsController.optionData[1]"></select>
</div>

更新指令:

angular.module('reporting.directive')

.directive("chosen", function () {

    var linker = function (scope, element, attr) {

        scope.$watch(
            function (scope) {
                return scope.selectsController.optionData
            }, function () {
                element.trigger('chosen:updated');
                console.log("fired for " + attr["id"]);
            });



        element.chosen({
            single_backstroke_delete: false,
            search_contains: true,
            no_results_text: "Oops, nothing found!",
            width: "100%"
        });
    };

    return {
        restrict: 'A',
        link: linker
    }
})
;

3 个答案:

答案 0 :(得分:0)

您的var launchd未绑定到list且无法观看。首先将它绑定到$ scope。

$scope

答案 1 :(得分:0)

我正在分享一些有用的angularJS概念,请参考下面的内容。

  1. 承诺只会在控制器调用的一生中执行一次。
  2. 当我们对任何变量应用观看时,观看将触发该变量的所有分配。
  3. var list = attr ['selected'];

      

    范围。$ watch(list,function(){               element.trigger( '选自:更新');           });

    list = attr ['再次选择'];

    在这种情况下,列表分配了2次,因此观看会触发两次。

答案 2 :(得分:0)

我想出了如何让它发挥作用。我不是100%的原因,但我确信下面的更改会导致Chosen select更新,并且由于数据/范围的变化而触发$ watch会按预期更新。

我将数据发送到隔离范围中的指令中,然后观察该var。在将其分配给范围(通过Controller As)之前,我还必须等待承诺解决。如果我没有等待承诺,我就不会得到更新。

指令:

angular.module('reporting.directive')

.directive("chosen", function () {

    var linker = function (scope, element, attr) {

        scope.$watch("data", function () {
                element.trigger('chosen:updated');
                console.log("fired for " + attr["id"]);
            });

        element.chosen({
            single_backstroke_delete: false,
            search_contains: true,
            no_results_text: "Oops, nothing found!",
            width: "100%"
        });
    };

    return {
        restrict: 'A',
        link: linker,
        scope: {
            data: "="
        }
    }
})
;

HTML /模板:

<div class="col-xs-12 col-md-2">
    <div class="filterboxtext">Cost Center</div>
    <select id="costcenter" class="chosen-select" chosen data-placeholder="ALL" multiple
            ng-model="csSelect1" ng-options="cc2 as cc2 for cc2 in selectsController.datacostcenter" data="selectsController.datacostcenter"></select>
</div>
<div class="col-xs-12 col-md-2">
    <div class="filterboxtext">Provider Name</div>
    <select id="providername" class="chosen-select" chosen data-placeholder="ALL" multiple ng-change="$state.forceReload()"
            ng-model="csSelect2" ng-options="provname as provname for provname in selectsController.dataprovname" data="selectsController.dataprovname"></select>
</div>

控制器:

angular.module('reporting.controller')

.controller('SelectsController', function (SelectDataRetrival,$q) {
    var selectsController = this;

    SelectDataRetrival.query({ stuff: stuff })
        .$promise.then(function (results) {
            selectsController.datacostcenter = results;
        });
    SelectDataRetrival.query({ stuff: stuff2 })
        .$promise.then(function (results) {
            selectsController.dataprovname = results;
        });

})
;