簡體   English   中英

Angular:帶有bindToController的指令會丟失數據

[英]Angular: directive with bindToController 'loses' data

我有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 ,如果不存在,它將設置為Actions 也不需要itemDescription 但是,如果我指定itemDescription ,則它始終在HTML DOM中可見,但是Actions對我而言卻表現得很奇怪:它設置為默認值Actions ,但在HTML DOM中卻不可見。 兩者之間的區別在於, actionsText是在控制器的代碼中顯式綁定this的-但我認為這是bindToController默認行為,當我要設置不存在value的默認值時,這就是我應該做的事情。 同樣,當我調試它時(例如,通過調用函數之一), actionsText具有undefined值,盡管事實是,如果在創建時調試它,它會設置默認的Actions值。 它不適用於一次性綁定(帶有::和正常情況。 也許是有scope: {}來自指令的代碼,但我無法弄清楚,希望對您有所幫助-謝謝您。 PS我嘗試從控制器返回viewModel變量-它沒有幫助。 PS 2如果指定actionsText (如data-actions-text={{'Something'}} ),則效果很好

您正在使用bindToController ,它間接將范圍值添加this上下文的控制器。 但是,由於您在bindToController表達式內使用@符號,因此發生了此問題。

只要有controllerAsbindToController和作用域@角的情況, bindToController以明顯不同的方式處理此問題。

實際上,當您在帶有controllerAsbindToController angular的隔離范圍內的范圍變量上使用@ ,在該attribute值給出的表達式上使用$observe進行監視, 對於相同的角度代碼

該解決方案將使用$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();
    };
};

這是詳細的版本答案

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM