【问题标题】:Angular: directive with bindToController 'loses' dataAngular:带有 bindToController 的指令“丢失”数据
【发布时间】:2015-10-16 05:18:31
【问题描述】:

我有actionButtons 指令:

function actionButtons(){
    'use strict';
    return {
        scope: {},
        restrict: 'AE',
        bindToController: {
            itemId: '@',
            itemDescription: '@',
            actionsText: '@',
            previewAction: '&',
            previewText: '@',
            editAction: '&',
            editText: '@',
            removeAction: '&',
            removeText: '@'
        },
        controller: ActionButtonsController,
        controllerAs: 'actionButtonsCtrl',
        templateUrl: 'src/views/directives/actionButtons.html'
    };
}

使用ActionButtonsController 控制器:

/**
 *
 * @constructor
 */
function ActionButtonsController() {
    'use strict';
    var viewModel = this;
    //not important assertions
    }
    /**
     *
     * @type {boolean}
     */
    viewModel.hasItemDescription = typeof viewModel.itemDescription === 'string' &&
        viewModel.itemDescription.length > 0;
    /**
     *
     * @type {string}
     */
    viewModel.previewText = viewModel.previewText || 'preview';
    /**
     *
     * @type {string}
     */
    viewModel.editText = viewModel.editText || 'edit';
    /**
     *
     * @type {string}
     */
    viewModel.removeText = viewModel.removeText || 'remove';
    /**
     *
     * @type {string}
     */
    viewModel.actionsText = viewModel.actionsText || 'Actions';

    viewModel.preview = function() {
        viewModel.previewAction();
    };

    viewModel.edit = function() {
        viewModel.editAction();
    };

    viewModel.remove = function() {
        viewModel.removeAction();
    };
}

他的模板的一部分,带有按钮:

<div class="visible-xs-block btn-group" data-dropdown>
<button class="btn btn-block btn-primary" id="{{::(actionButtonsCtrl.itemId)}}" type="button"
        data-dropdown-toggle aria-haspopup="true">
    {{actionButtonsCtrl.actionsText}} <span class="sr-only" data-ng-if="::actionButtonsCtrl.hasItemDescription">
        for {{::(actionButtonsCtrl.itemDescription)}}</span></button>
</div>

这就是我在应用程序中的称呼:

<td class="col-md-3 col-xs-3 text-center">
    <div data-action-buttons
         data-item-id="{{author.id + '_' + author.name + '_' + author.surname}}"
         data-item-description="{{author.name + ' ' + author.surname}}"
         data-preview-action="authorCtrl.preview(author)"
         data-edit-action="authorCtrl.edit(author)"
         data-remove-action="authorCtrl.remove(author)"
        ></div>
</td>

问题是:从控制器代码中可以看出,例如 actionsText 不是必需的,如果不存在,它将被设置为 ActionsitemDescription 也不是必需的。但是如果我指定itemDescription,它在HTML DOM 中一直可见,但Actions 的行为对我来说非常奇怪:它设置为默认值Actions,但它在HTML DOM 中不可见。这两者之间的区别在于actionsText 在控制器的代码中明确地绑定到this - 但我认为这是bindToController 的默认行为,当我想设置默认值而不是值时我应该这样做展示。此外,当我调试它时(例如通过调用其中一个函数),actionsText 具有undefined 值,尽管如果我在创建它时对其进行调试,它已经设置了默认的Actions 值。它不适用于一次性绑定(使用::)和正常情况。也许它与指令代码中的scope: {} 有关,但我无法弄清楚,我希望能得到你的帮助 - 提前谢谢你。 P.S. 我尝试从控制器返回 viewModel 变量 - 它没有帮助。 附注2 如果指定actionsText 效果很好(如data-actions-text={{'Something'}}

【问题讨论】:

    标签: javascript angularjs angularjs-directive angularjs-controller angularjs-controlleras


    【解决方案1】:

    您正在使用bindToController,它间接将范围值添加到控制器this 上下文中。但是这个问题正在发生,因为您在 bindToController 表达式中使用了 @ 符号。

    只要有controllerAsbindToController@ 的范围,角度处理这个东西的方式就完全不同了。

    实际上,当您在具有controllerAsbindToController 的隔离范围内的范围变量上使用@ 时,角度会在attribute 值上给出的表达式上使用$observe 进行监视,angular code for same

    该解决方案将使用$timeout 来执行所有将使用@ 的独立范围值获取的分配。因为在评估 $observe 表达式之后,值会在下一个摘要循环周期中绑定。

    代码

    function ActionButtonsController() {
        'use strict';
        var viewModel = this;
        $timeout(function() {
            viewModel.hasItemDescription = typeof viewModel.itemDescription === 'string' &&
                viewModel.itemDescription.length > 0;
    
            viewModel.previewText = viewModel.previewText || 'preview';
    
            viewModel.editText = viewModel.editText || 'edit';
    
            viewModel.removeText = viewModel.removeText || 'remove';
    
            viewModel.actionsText = viewModel.actionsText || 'Actions';
        })
    
        viewModel.preview = function() {
            viewModel.previewAction();
        };
    
        viewModel.edit = function() {
            viewModel.editAction();
        };
    
        viewModel.remove = function() {
            viewModel.removeAction();
        };
    };
    

    这是detailed version answer

    【讨论】:

    • @Pneumokok 如果您想要详细的答案,您可以查看链接的答案。这将有助于清除您的概念。很高兴为您提供帮助。谢谢 :)
    • @Pankaj Parkar bindToController 很有用,但如果我还想做一些 DOM 操作怎么办?我必须再次使用链接功能吗?
    • @Levis 是的..你应该..因为你会在那里得到角度编译的指令元素..在那里操作 DOM 会更安全。
    • @Pankaj Parkar 所以,如果我使用了 controllerAs:"ctrl",我可以使用 require:'ctrl' 获取控制器并将其作为链接函数中的第四个参数注入吗?..因为我想要防止在指令中使用范围选项
    猜你喜欢
    • 2016-06-22
    • 2016-04-30
    • 2015-10-03
    • 1970-01-01
    • 1970-01-01
    • 2017-10-01
    • 1970-01-01
    • 2016-05-24
    • 1970-01-01
    相关资源
    最近更新 更多