如何在自定义指令中获取ng-model值

时间:2014-03-06 22:15:08

标签: angularjs angularjs-directive

我在这里搜索了SO并尝试了我找到的答案,但我似乎无法从我的自定义指令的ngModel中获取模型值。

enter image description here

这是指令

/*
 *usage: <markdown ng:model="someModel.content"></markdown>
 */
breathingRoom.directive('markdown', function () {
    var nextId = 0;
    return {
        require: 'ngModel',
        replace: true,
        restrict: 'E',
        template: '<div class="pagedown-bootstrap-editor"></div>',
        link:function (scope, element, attrs, ngModel) {

            var editorUniqueId = nextId++;
            element.html($('<div>' +
                '<div class="wmd-panel">' +
                '<div id="wmd-button-bar-' + editorUniqueId + '"></div>' +
                '<textarea class="wmd-input" id="wmd-input-' + editorUniqueId + '">{{modelValue()}}' +
                '</textarea>' +
                '</div>' +
                '<div id="wmd-preview-' + editorUniqueId + '" class="wmd-panel wmd-preview"></div>' +
                '</div>'));

            var converter = new Markdown.Converter();

            var help = function () {
                // 2DO: add nice modal dialog
                alert("Do you need help?");
            };

            var editor = new Markdown.Editor(converter, "-" + editorUniqueId, {
                handler: help
            });

            editor.run();


            // local -> parent scope change (model)
            jQuery("#wmd-input-" + editorUniqueId).on('change', function () {
                var rawContent = $(this).val();
                ngModel.$setViewValue(rawContent);
                scope.$apply();
            });

            // parent scope -> local change
            scope.modelValue = function () {
                console.log('modelvalue - ', ngModel.$viewValue);
                return ngModel.$viewValue;
            };
        }
    };
});

这是HTML

<markdown ng-class="{error: (moduleForm.Description.$dirty && moduleForm.Description.$invalid) || (moduleForm.Description.$invalid && submitted)}"
          id="Description" 
          name="Description" 
          placeholder="Description" 
          ng-model="module.description" 
          required></markdown>   

这里的问题是输出只是

{{modelValue()}}

我也尝试过创建私有方法

function getModelValue() {
    console.log(ngModel.$viewValue);
    return ngModel.$viewValue;
}

然后将一个模板行更改为

'<textarea class="wmd-input" id="wmd-input-' + editorUniqueId + '">' + getModelValue() +

但输出是

NaN

我哪里错了?


如果重要,这是我的脚本的顺序(不包括供应商脚本)

<script src="app.js"></script>
<script src="directives/backButtonDirective.js"></script>
<script src="directives/bootstrapSwitchDirective.js"></script>
<script src="directives/markdownDirective.js"></script>
<script src="directives/trackActiveDirective.js"></script>
<script src="services/alertService.js"></script>
<script src="services/roleService.js"></script>
<script src="services/moduleService.js"></script>
<script src="services/changePasswordService.js"></script>
<script src="services/userService.js"></script>
<script src="controllers/usersController.js"></script>
<script src="controllers/userController.js"></script>
<script src="controllers/moduleController.js"></script>
<script src="controllers/modulesController.js"></script>

4 个答案:

答案 0 :(得分:13)

您的插入未编译的HTML。最简单的方法是将其移入模板,或使用ng-transclude进行调查。以下是将其移入模板的示例。

plunker

breathingRoom.directive('markdown', function () {
    var nextId = 0;
    return {
        require: 'ngModel',
        replace: true,
        restrict: 'E',
        template: '<div class="pagedown-bootstrap-editor"><div class="wmd-panel">' +
                '<div id="wmd-button-bar-{{editorUniqueId}}"></div>' +
                '<textarea class="wmd-input" id="wmd-input-{{editorUniqueId}}">{{modelValue()}}' +
                '</textarea>' +
                '</div>' +
                '<div id="wmd-preview-{{editorUniqueId}}" class="wmd-panel wmd-preview"></div>' +
                '</div></div>',
        link:function (scope, element, attrs, ngModel) {

            scope.editorUniqueId = nextId++;

            // parent scope -> local change
            scope.modelValue = function () {
                console.log('modelvalue - ' + ngModel.$viewValue);
                return ngModel.$viewValue;
            };
        }
    };
});

答案 1 :(得分:10)

您实际上并没有解析模型,因为{{modelValue()}}表达式只是您在链接函数中构建的HTML字符串的一部分。

您应该将编辑器标记移至template,以便绑定到ng-model

假设目标是为Markdown编辑器创建必要的HTML标记,然后显示转换标记的预览,我会将其分为两个角色:

  1. 自定义标记的指令
  2. 实际将值转换为markdown的过滤器:
  3. 标记:

    <div ng-app="app" ng-controller="DemoCtrl">
        <h3>Markdown editor</h3>
        <markdown-editor ng-model="markdown"></markdown-editor>
    </div>
    

    JavaScript的:

    var app = angular.module('app', []);
    
    app.filter('markdown', function () {
        return function (input) {
            return input.toUpperCase(); // this is where you'd convert your markdown
        };
    });
    
    app.directive('markdownEditor', function () {
        return {
            restrict: 'E',
            scope: {
                ngModel: "="
            },
            template:
                '<div>' +
                '<textarea ng-model="ngModel"></textarea>' +
                '<div class="preview">{{ ngModel | markdown }}</div>' +
                '</div>'
        };
    });
    
    app.controller('DemoCtrl', function ($scope) {
        $scope.markdown = "**hello world**";
    });
    

    =范围在传递给ng-model{{ ngModel | markdown }}的属性上设置双向绑定,将ngModel的值传递给markdown过滤器。

    http://jsfiddle.net/benfosterdev/jY3ZK/

答案 2 :(得分:3)

查看angular的parse服务。它使您可以获取和设置ng-model中引用的属性值。

link: function(scope, elem, attrs) {
    var getter = $parse(attrs.ngModel);
    var setter = getter.assign;
    var value = getter(scope);
    setter(scope, 'newValue');
}

答案 3 :(得分:2)

最简单的方法是:

如果ngModel变量位于范围的顶层

link: function(scope, elem, attrs) {
    if (attrs.ngModel) {
        var myModelReference = scope[attrs.ngModel];
    }
}

如果ngModel引用深度嵌套在范围内的属性(最佳方式)

(因此,对于scope.prop1.prop2attrs.ngModel将是&#34; prop1.prop2&#34;),因为您无法查找scope['prop1.prop2']你需要通过将字符串键转换为实际的嵌套键来挖掘。

为此,我推荐Lodash _.get()功能

link: function(scope, elem, attrs) {
    if (attrs.ngModel) {
        var myModelReference = _.get(scope, attrs.ngModel);
    }
}