如何将模型传递给自定义指令

时间:2014-04-21 15:25:46

标签: angularjs angularjs-directive angularjs-scope

我的目标是将projectName模型从我的MainController传递到我的自定义contenteditable指令。

我有以下控制器:

app.controller("MainController", function($scope){
    $scope.projectName = "Hot Air Balloon";
});

以下是我如何调用该指令:

<div class="column" ng-controller="MainController">
    <h2 contenteditable name="myWidget" ng-model="projectName" strip-br="true"></h2>
    <p>{{projectName}}</p>
</div>

我已按照本教程获得了满足指令:https://docs.angularjs.org/api/ng/type/ngModel.NgModelController

如果我正确理解文档,那么Angular将不会使用我想要的模型。相反,它将创建一个新的模型w /本地范围的contenteditable指令。我知道我可以在指令中添加一个隔离范围,但我不知道如何使用传递给链接函数中隔离范围的模型。

我尝试过类似下面的东西但没有用......

<h2 contenteditable item="projectName"></h2>

---指令代码---

scope: {
    item: '=item'
}

link: function(){
    ...
    item.$setViewValue(...)
    ...
}

---我的原始指令调用 -

<div class="column" ng-controller="MainController">
    <h2 contenteditable name="myWidget" ng-model="projectName" strip-br="true"></h2>
    <p>{{projectName}}</p>
</div>

---我的原始控制器和指令---

app.controller("MainController", function($scope){
    $scope.projectName = "LifeSeeds";
});

app.directive('contenteditable', function(){
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, element, attrs, ngModel){
            console.log(ngModel);

            if(!ngModel) return;

            console.log(ngModel.$viewValue);

            ngModel.$render = function(){
                element.html(ngModel.$viewValue || '');
            };

            element.on('blur keyup change', function(){
                scope.$apply(read);
            });
            read();

            function read(){
                var html = element.html();
                if(attrs.stripBr && html == '<br>'){
                    html = '';
                }
                ngModel.$setViewValue(html);
            }

        }
    };
});

2 个答案:

答案 0 :(得分:2)

您可以将ng-model与您自己的指令一起使用。要确保包含该属性,您可以使用以下属性require

app.directive("myDirective", function(){ return { require:"ngModel", link: function(scope, element, attr, ngModel){ console.log(ngModel); } } });

然后,您可以在指令中编写您想要的ng-model行为。

答案 1 :(得分:1)

工作解决方案:http://plnkr.co/edit/Lu1ZG9Lpx2sl8CYe8FCx?p=preview

我提到我在原帖中尝试使用隔离范围。

<h2 contenteditable item="projectName"></h2>

这实际上是正确的方法,所以使用指令链接函数的模型参数忽略我的完整原始示例。

link: function(scope, element, attrs, ngModel)

隔离范围方法不起作用的原因是$ scope.projectName存储了一个原语而不是一个对象。我不懂一些javascript基础知识。主要是,我不知道原始类型是按值传递给函数的。

基元在javascript中按值传递。因此,对函数中的原始值所做的更改不会更改传递给函数的变量的值。

function changeX(x){
    x = 5;
}
x = 4;
changeX(x);
console.log(x) // will log 4 ...  Not 5

但是,传递给javascript函数的对象是通过引用传递的,因此函数中对它们的修改将被传递给传递给函数的变量。

我的问题在于如何在MainController中声明范围。

我有:

$scope.projectName = "LifeSeeds";

这是一个原始的。当我将projectName传递给指令时,我传递了一个原语。

<h2 contenteditable item="projectName"></h2>

因此,对可编辑元素的更改是针对指令中的值而不是针对存储在MainController范围中的值。解决方案是将值存储在MainController范围内的对象中。

// correct
$scope.project = {
    html: "Editable Content"
};

// wrong
$scope.projectName = "Editable Content"