programing

Angular 형식의 동적 유효성 검사 및 이름JS

powerit 2023. 3. 9. 22:24
반응형

Angular 형식의 동적 유효성 검사 및 이름JS

다음 양식이 있습니다.http://jsfiddle.net/dfJeN/

입력의 이름 값이 정적으로 설정되어 있는 것을 알 수 있습니다.

name="username"

폼 검증은 정상적으로 동작합니다(입력에서 텍스트를 모두 삭제하고 텍스트를 표시해야 합니다).

그런 다음 이름 값 http://jsfiddle.net/jNWB8/을 동적으로 설정합니다.

name="{input.name}"

그리고 이것을 내 검증에 적용합니다.

login.{{input.name}}.$error.required

(이 패턴은 ng-module에서 사용됩니다) 하지만 폼 검증이 깨졌습니다.브라우저에서는 올바르게 해석됩니다(요소를 조사하면 login.username이 표시됩니다).$error.required).

감 잡히는 게 없어요?

편집: 콘솔에 스코프를 기록하면

{{input.name}}

식은 보간되지 않습니다.{{input.name}} 애트리뷰트로서의 내 폼은 사용자 이름이 없습니다.

업데이트: 1.3.0-rc.3 name="{input.name}"은 정상적으로 동작합니다.#1404 참조

그런 식으로 할 수는 없어요.

ng-repeat과 같은 요소를 폼에 동적으로 추가할 필요가 있다고 가정할 때 ng-form을 사용하여 이러한 개별 항목을 검증할 수 있도록 해야 합니다.

<form name="outerForm">
<div ng-repeat="item in items">
   <ng-form name="innerForm">
      <input type="text" name="foo" ng-model="item.foo" />
      <span ng-show="innerForm.foo.$error.required">required</span>
   </ng-form>
</div>
<input type="submit" ng-disabled="outerForm.$invalid" />
</form>

안타깝게도, Angular의 특징은 잘 문서화되어 있지 않습니다.

네스트된 ngForm을 사용하면 HTML 템플릿 내에서 특정 입력 컨트롤러에 액세스할 수 있습니다.다만, 다른 컨트롤러로부터 액세스 하는 경우는 도움이 되지 않습니다.

예.

<script>
  function OuterController($scope) {
    $scope.inputName = 'dynamicName';

    $scope.doStuff = function() {
      console.log($scope.formName.dynamicName); // undefined
      console.log($scope.formName.staticName); // InputController
    }
  }
</script>

<div controller='OuterController'>
  <form name='myForm'>
    <input name='{{ inputName }}' />
    <input name='staticName' />
  </form>
  <a ng-click='doStuff()'>Click</a>
</div>

이 명령어를 사용하여 문제를 해결합니다.

angular.module('test').directive('dynamicName', function($compile, $parse) {
  return {
    restrict: 'A',
    terminal: true,
    priority: 100000,
    link: function(scope, elem) {
      var name = $parse(elem.attr('dynamic-name'))(scope);
      // $interpolate() will support things like 'skill'+skill.id where parse will not
      elem.removeAttr('dynamic-name');
      elem.attr('name', name);
      $compile(elem)(scope);
    }
  };
});

이제 필요에 따라 'name' 속성 대신 'dynamic-name' 속성만 사용할 수 있습니다.

예.

<script>
  function OuterController($scope) {
    $scope.inputName = 'dynamicName';

    $scope.doStuff = function() {
      console.log($scope.formName.dynamicName); // InputController
      console.log($scope.formName.staticName); // InputController
    }
  }
</script>

<div controller='OuterController'>
  <form name='myForm'>
    <input dynamic-name='inputName' />
    <input name='staticName' />
  </form>
  <a ng-click='doStuff()'>Click</a>
</div>

Github에 대한 이 논의에 따르면 이 문제는 AngularJS 1.3에서 수정되어야 합니다.

한편, @caitp @Thinkscape 의해 작성된 임시 솔루션을 다음에 나타냅니다.

// Workaround for bug #1404
// https://github.com/angular/angular.js/issues/1404
// Source: http://plnkr.co/edit/hSMzWC?p=preview
app.config(['$provide', function($provide) {
    $provide.decorator('ngModelDirective', function($delegate) {
        var ngModel = $delegate[0], controller = ngModel.controller;
        ngModel.controller = ['$scope', '$element', '$attrs', '$injector', function(scope, element, attrs, $injector) {
            var $interpolate = $injector.get('$interpolate');
            attrs.$set('name', $interpolate(attrs.name || '')(scope));
            $injector.invoke(controller, this, {
                '$scope': scope,
                '$element': element,
                '$attrs': attrs
            });
        }];
        return $delegate;
    });
    $provide.decorator('formDirective', function($delegate) {
        var form = $delegate[0], controller = form.controller;
        form.controller = ['$scope', '$element', '$attrs', '$injector', function(scope, element, attrs, $injector) {
            var $interpolate = $injector.get('$interpolate');
            attrs.$set('name', $interpolate(attrs.name || attrs.ngForm || '')(scope));
            $injector.invoke(controller, this, {
                '$scope': scope,
                '$element': element,
                '$attrs': attrs
            });
        }];
        return $delegate;
    });
}]);

JSFiddle에서 데모합니다.

@En의 나이스한 곡ISeeK...하지만 좀 더 우아하고 다른 지시들에 대한 간섭을 줄였어요.

.directive("dynamicName",[function(){
    return {
        restrict:"A",
        require: ['ngModel', '^form'],
        link:function(scope,element,attrs,ctrls){
            ctrls[0].$name = scope.$eval(attrs.dynamicName) || attrs.dynamicName;
            ctrls[1].$addControl(ctrls[0]);
        }
    };
}])

EnlSeek 솔루션보다 조금 개선되었습니다.

angular.module('test').directive('dynamicName', ["$parse", function($parse) {
 return {
    restrict: 'A',
    priority: 10000, 
    controller : ["$scope", "$element", "$attrs", 
           function($scope, $element, $attrs){
         var name = $parse($attrs.dynamicName)($scope);
         delete($attrs['dynamicName']);
         $element.removeAttr('data-dynamic-name');
         $element.removeAttr('dynamic-name');
          $attrs.$set("name", name);
    }]

  };
}]);

여기 플런커 재판이 있습니다.자세한 설명은 이쪽입니다.

@caitp 및 @Thinkscape 솔루션을 조금 확장하면 다음과 같이 ng 형식이 동적으로 생성됩니다.

<div ng-controller="ctrl">
    <ng-form name="form">
        <input type="text" ng-model="static" name="static"/>

        <div ng-repeat="df in dynamicForms">
            <ng-form name="form{{df.id}}">
                <input type="text" ng-model="df.sub" name="sub"/>
                <div>Dirty: <span ng-bind="form{{df.id}}.$dirty"></span></div>
            </ng-form>
        </div>

        <div><button ng-click="consoleLog()">Console Log</button></div>
        <div>Dirty: <span ng-bind="form.$dirty"></span></div>
    </ng-form>      
</div>

JSFiddle에 대한 데모입니다.

나는 Ben Lesh의 솔루션을 사용했고 그것은 나에게 잘 작동한다.하지만 제가 직면했던 한 가지 문제는 이너 폼을 추가했을 때ng-form, 모든 폼의 스테이트는 다음과 같습니다.form.$valid, form.$error etc etc etc etc etc etc etc etc .ng-submit★★★★★★ 。

예를 들어 다음과 같습니다.

<form novalidate ng-submit="saveRecord()" name="outerForm">
    <!--parts of the outer form-->
    <ng-form name="inner-form">
      <input name="someInput">
    </ng-form>
    <button type="submit">Submit</button>
</form>

그리고 내 컨트롤러:

$scope.saveRecord = function() {
    outerForm.$valid // this is undefined
}

따라서 폼을 제출하기 위해 정기적인 클릭 이벤트를 사용해야 했습니다.이 경우 폼 오브젝트를 전달해야 합니다.

<form novalidate name="outerForm">  <!--remove the ng-submit directive-->
    <!--parts of the outer form-->
    <ng-form name="inner-form">
      <input name="someInput">
    </ng-form>
    <button type="submit" ng-click="saveRecord(outerForm)">Submit</button>
</form>

또한 변경된 컨트롤러 방식:

$scope.saveRecord = function(outerForm) {
    outerForm.$valid // this works
}

왜 그런지는 잘 모르겠지만 누군가에게 도움이 되길 바란다.

이 문제는 Angular 1.3+에서 수정되었습니다.이 구문은 사용자가 수행하려는 작업에 대한 올바른 구문입니다.

login[input.name].$invalid

다음과 같은 입력의 동적 이름을 설정하면

<input name="{{dynamicInputName}}" />

그리고 아래 코드와 같은 동적 이름에 대해 set validation을 사용합니다.

<div ng-messages="login.dynamicInputName.$error">
   <div ng-message="required">
   </div>
</div>

언급URL : https://stackoverflow.com/questions/14378401/dynamic-validation-and-name-in-a-form-with-angularjs

반응형