Пользовательская директива AngularJS не удаляет директиву ng-required в дочерних элементах

#angularjs #angular-directive

#angularjs #angular-директива

Вопрос:

Приведенная ниже директива работает нормально, пока вы не введете ng-required директиву в дочерний div.

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

Текущее решение для исправления, которое мы имеем для этой директивы (которое было сделано кем-то, кто больше не работает в компании), заключается в том, чтобы ввести ng-if директиву для того же элемента, что и пользовательская директива. Это, очевидно, противоречит цели пользовательской директивы, и теперь, когда мне нужно добавить дополнительные условия, их необходимо исправить.

Я читал другие сообщения и считаю, что проблема связана с областью действия директивы. Тем не менее, я поиграл с параметрами уровня области видимости, а также вышел из области видимости в консоли, чтобы искать метод в стиле уничтожения без какого-либо успеха.

В случае, если реклама видит представление, он, правильно, не увидит html ниже из-за уровня пользователя, равного 3. И все же требование остается…

ПОЛЬЗОВАТЕЛЬСКАЯ ДИРЕКТИВА:

 angular.module('tvalorApp').directive('checkPermissions', ['PermissionsServices', function(PermissionsServices) {
return {
    restrict: 'A',
    scope: {
        level:'@'
    },
    link: function(scope, elem, attrs, ctrl) {          
        
        function checkPermission() {
            if (attrs.permissions != '') {
                var hasPermission = PermissionsServices.hasAccess(attrs.checkPermissions, scope.level);

                if (!hasPermission) {
                    console.log(scope)
                    elem.remove();
                }
            } else {
                elem.remove();
            }
        }
                
        scope.$watch('level', function(value) {
            checkPermission();
        });
    }
};
}]);
 

ФАБРИКА, ИСПОЛЬЗУЕМАЯ ДИРЕКТИВОЙ:

 angular.module('tvalorApp').factory('PermissionsServices', PermissionsServices);

function PermissionsServices() {
    
var fields = {
    
    "noAdmin": [false, true, true],
    "noValidator": [true, false, true],
    "noCommercial": [true, true, false],
    "onlyAdmin": [true, false, false],
    "onlyValidator": [false, true, false],
    "onlyCommercial": [false, false, true],
    "allUsers": [true, true, true],
    "noUsers": [false, false, false],
};

var readOnlyFields = {
    
    "protectAdmin": [true, false, false],
    "protectValidator": [false, true, false],
    "protectCommercial": [false, false, true],
    "noProtectAdmin": [false, true, true],
    "noProtectValidator": [true, false, true],
    "noProtectCommercial": [true, true, false],
    "noProtect": [false, false, false],
    "protectAll": [true, true, true],
};

var hasAccess = function(stateName, level) {
    var hasAccess = false,
    level = level - 1;
    if(fields[stateName][level]) {
        hasAccess = true;
    }
    return hasAccess;
};

var checkReadOnlyField = function(fieldName, level) {
    return readOnlyFields[fieldName][level - 1];
}

return {
    hasAccess: hasAccess,
    checkReadOnlyField: checkReadOnlyField
};
};
 

HTML:

 <div class="form-group" level="{{taskCtrl.level}}" check-permissions="noCommercial">
                    <label for="a_market">
                        Situación del mercado <span class="highlight">*</span>
                    </label>
                    <select id="a_market" name="a_market" class="form-control" ng-change="taskCtrl.setEditTask()"
                        ng-options="item.id as item.es for item in mainCtrl.market" ng-model="taskCtrl.task.a_id_market"
                        ng-required="true">
                        <option value="">N.A.</option>
                    </select>
                    <p class="error-message" ng-show="taskForm.a_market.$dirty amp;amp; taskForm.a_market.$error.required">Campo
                        Obligatorio</p>
                </div>
 

Ответ №1:

Проблема здесь в том, что, когда пользовательская директива удаляет элемент div, элемент управления формой остается зарегистрированным в родительской форме.

Одним из решений было бы отменить регистрацию этого элемента управления при удалении элемента, используя $removeControl(control); метод. (документация)

Для этого, прежде всего, вам нужно ввести ссылку на родительскую форму в пользовательскую директиву:

 require: '^form',
 

и имя элемента управления, например:

 scope: {
    level: '@',
    field: '@'
  },
 

Теперь в функции link у вас есть доступ к родительской форме:

  link: function(scope, elem, attrs, ctrl) {
    console.log('parent form', ctrl);
  ...
  }
 

и вы можете отменить регистрацию элемента управления, который удаляется:

 if (!hasPermission) {
     elem.remove();
     ctrl.$removeControl(ctrl[scope.field]);
}
 

После этих дополнений, когда элемент удаляется, форма становится допустимой для отправки.

Вот рабочий пример: ДЕМОНСТРАЦИЯ

Комментарии:

1. Спасибо Биллу за ваш высоко оцененный ответ. Теперь я понимаю логику происходящего, но все еще не могу удалить ее из элемента управления. В вашем примере форма недействительна при отправке, несмотря на то, что уровень равен 2. Кроме того, вы не передаете поле, как мы делаем с level, и поэтому в моей версии поле все еще не определено…

2. В моем примере, если вы измените уровень на ‘3’, он воспроизводит регистр, и форма становится действительной

3. Я не совсем понимаю ваше последнее предложение, если вы хотите объяснить подробнее

4. Извините, я хотел сказать 3. Когда я меняю уровень на 3, он по-прежнему выдает «недопустимый».

5. Извинения. Я не знаком с jsfiddle.