Подтвердить что ты не робот

Как получить значение ng-model внутри пользовательской директивы

Я искал здесь на 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>
4b9b3361

Ответ 1

В HTML-формате ваша вставка не скомпилирована. Легче всего переместить его в свой шаблон или исследовать с помощью ng-translcude. Здесь приведен пример перемещения его в ваш шаблон.

http://plnkr.co/edit/cidTZLY9GpESMvCcHKBU?p=preview

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;
            };
        }
    };
});

Ответ 2

Фактически вы не решали вашу модель, поскольку выражение {{modelValue()}} было только частью строки HTML, которую вы строили в функции ссылок.

Вы должны переместить разметку редактора в template, чтобы вы могли привязываться к ng-model.

Предполагая, что цель состоит в том, чтобы создать необходимую разметку HTML для Markdown Editor, а затем показать предварительный просмотр преобразованной метки, я бы разделил ее на две роли:

  • Директива для пользовательской разметки
  • Фильтр для фактического преобразования значения в уценку:

Разметка:

<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/

Ответ 3

Самый простой способ:

Если переменная ngModel находится на верхнем уровне области

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

Если ngModel ссылается на свойство, глубоко вложенное в область (лучший способ)

(так что для scope.prop1.prop2, attrs.ngModel будет "prop1.prop2" ), и поскольку вы не можете просто искать scope['prop1.prop2'], вам нужно вникнуть, переведя строковый ключ в фактические вложенные ключи.

Для этого я рекомендую функцию Lodash _.get()

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

Ответ 4

Посмотрите angular parse сервис. Он позволяет получить и установить значение свойства, на которое ссылаются в ng-модели.

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