গতিশীল বৈধতা এবং AngularJS সহ একটি ফর্মের নাম


98

আমার এই ফর্মটি রয়েছে: http://jsfiddle.net/dfJeN/

আপনি দেখতে পাচ্ছেন ইনপুটটির জন্য নামের মানটি স্থিরভাবে সেট করা আছে:

name="username"

, ফর্ম বৈধতা ঠিকঠাক কাজ করে (কিছু যুক্ত করুন এবং ইনপুট থেকে সমস্ত পাঠ্য অপসারণ করুন, একটি পাঠ্য অবশ্যই উপস্থিত হবে)।

তারপরে আমি গতিরূপে নামটির মান সেট করার চেষ্টা করব: http://jsfiddle.net/jNWB8/

name="{input.name}"

তারপরে আমি আমার বৈধতার সাথে এটি প্রয়োগ করি

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

(এই প্যাটার্নটি এনজি-রিপিটে ব্যবহৃত হবে) তবে আমার ফর্মের বৈধতা ভঙ্গ হয়েছে। এটি আমার ব্রাউজারে সঠিকভাবে ব্যাখ্যা করা হয়েছে (আমি যদি উপাদানটি দেখেছি যা আমি login.username দেখেছি।। ত্রুটি.প্রাপ্ত) qu

কোন ধারণা ?

সম্পাদনা: কনসোলে স্কোপ লগ করার পরে এটি প্রদর্শিত হয়

{{input.name}}

এক্সপ্রেশন বিচ্ছিন্ন হয় না। আমার ফর্মটি {{ইনপুট.নেম}} বৈশিষ্ট্য হিসাবে তবে কোনও ব্যবহারকারীর নাম নেই।

আপডেট: 1.3.0-rc.3 নাম = "{{ইনপুট.নেম}}" প্রত্যাশার মতো কাজ করে। দয়া করে # 1404 দেখুন


কিছু গবেষণার পরে আমি এটি দেখতে পেলাম: "একবার এমন দৃশ্যে যখন এনজি বাইন্ডের ব্যবহারটি {{এক্সপ্রেশন} inding বাঁধনের চেয়ে বেশি পছন্দ হয় যখন কৌনিকটি সংকলনের আগে ব্রাউজারের দ্বারা তার কাঁচা অবস্থায় ক্ষণে ক্ষণে প্রদর্শিত হয় এমন টেম্পলেটে বাঁধাই পছন্দ করা যায়" । এই পৃষ্ঠায় ডকস.আঙ্গুলারজেএস.আর.পিআই / এনটি.ডাইরেক্টিভ: জিনবিন্ড , আমি যা করার চেষ্টা করছি তার জন্য এটি একটি ভাল শুরু বলে মনে হচ্ছে। আমি কোনও সমাধান খুঁজে পেলে এই পোস্টটি আপডেট করা হবে।
IxDay


উত্তরের যে কোনওটি আপনার সমস্যা সমাধান করেছেন। যদি তা হয় তবে দয়া করে সিকেকমার্ক এর স্কোরকে ক্লিক করে উত্তর হিসাবে চিহ্নিত করুন।
রিকার্ডো সুজা

এখানে এই ব্লগ নিবন্ধটি দেওয়া হয়েছে যা সম্ভবত এই সমস্যাটি প্রকাশিত অন্যদের জন্য কিছুটা সহায়ক হতে পারে: thebhwgroup.com/blog/2014/08/angularjs-html-form-design-part-2
পিফরাঞ্চাইজ

উত্তর:


176

আপনি যেভাবে চেষ্টা করছেন তা আপনি করতে পারবেন না।

আপনি যা করতে চেষ্টা করছেন তা ধরে নিচ্ছেন এনজি-রিপিটের মতো কিছু দিয়ে আপনার কোনও গতিশীলভাবে উপাদানগুলিকে যুক্ত করতে হবে , সেই স্বতন্ত্র আইটেমগুলির বৈধতা দেওয়ার জন্য আপনাকে নেস্টেড এনজি-ফর্ম ব্যবহার করতে হবে :

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

দুঃখের বিষয়, এটি কৌণিকর কোনও ঠিকঠাক বৈশিষ্ট্য নয়।


11
আপনি কীভাবে শেষ পর্যন্ত এটি সমাধান করবেন? আমি এখনও দেখতে পাই না যে এই নির্দিষ্ট উত্তরটি আপনার সমস্যার সাথে কীভাবে সম্পর্কিত - কারণ এটি গতিশীলভাবে উত্পন্ন ফর্ম ক্ষেত্র এবং নামগুলি দেখায় না?
ওডম্যান

7
এটি একটি সম্পূর্ণ সমাধান (বা workaround) এবং কৌণিক দল দ্বারা প্রস্তাবিত পদ্ধতির ( docs.angularjs.org/api/ng.directive:form থেকে ): "যেহেতু আপনি ইন্টারপোলেশন ব্যবহার করে ইনপুট উপাদানগুলির নাম বৈশিষ্ট্যকে গতিশীলভাবে তৈরি করতে পারবেন না you এনজিফর্ম নির্দেশনায় বারবার ইনপুটগুলির প্রতিটি সেট মোড়াতে হবে এবং এগুলি একটি বাহ্যিক ফর্ম উপাদানগুলিতে নীড় করে। " প্রতিটি নেস্টেড ফর্মের নিজস্ব সুযোগ রয়েছে যা এটি কাজ করতে দেয়।
নরেম্যাক

4
এই উদাহরণ এবং পরামর্শটি এখনও গতিশীল "নাম" কে সম্বোধন করে না। দেখে মনে হচ্ছে এগুলি আপনাকে গতিময়ভাবে ক্ষেত্রগুলির 'ক্লোনড' সেটগুলিতে বাসা বাঁধার অনুমতি দিতে চায় তবে প্রতিটি ক্ষেত্রের অন্তর্নিহিত নাম অবশ্যই স্থির থাকতে হবে।
দ্বিগুণ করুন

4
@ থিনিস হ্যাঁ এটি সাহায্য করে। এই সমাধানের সাথে নামটির গতিশীল হওয়ার দরকার নেই। এটি আপনার পছন্দ মতো যে কোনও কিছু হতে পারে (যেমন "ফু")। মুল বক্তব্যটি হ'ল শিশু ফর্মটির নিজস্ব সুযোগ রয়েছে, সুতরাং বৈধতা প্রকাশগুলি কেবল ইনারফর্ম.ফু $ ত্রুটি ইত্যাদি উল্লেখ করতে পারে n এনজি-মডেল তারপরে প্যারেন্ট স্কোপটিতে আপনি যা চান তা ইঙ্গিত করতে পারে (সম্ভবত গতিশীল)।
জেদ রিচার্ডস

@thinice - উইনটামেট ঠিক আছে। আপনি সরাসরি ফর্মটি জমা দিচ্ছেন না বলে গতিশীল নামের প্রয়োজন নেই। উদ্দেশ্যটি হল কিছু মডেল পরিবর্তন করা, তারপরে এটি অ্যাজাক্সের মাধ্যমে পোস্ট করুন। গতিশীল নামগুলি সেই মুহুর্তে আপনার কাছে কিছুই যাবে না। যদি আপনি প্রকৃতপক্ষে কোনও এইচটিএমএল ফর্ম জমা ব্যবহার করছেন তবে আপনি কিছু অদ্ভুত / ভুল করছেন, এবং আপনার আলাদা পদ্ধতির প্রয়োজন হবে।
বেন লেশ

44

নেস্টেড এনজিএফর্ম ব্যবহার আপনাকে 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);
    }
  };
});

এখন আপনি ডাইনামিক নাম ব্যবহার করুন যেখানেই প্রয়োজন সেখানে 'নাম' বৈশিষ্ট্যের পরিবর্তে কেবল 'গতিশীল-নাম' বৈশিষ্ট্যটি।

যেমন

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

4
আমি এই সমাধানটি $interpolateপরিবর্তে ব্যবহার না করে ব্যতীত $parseআরও বেশি দরকারী বলে মনে করেছি
TheRocketSurgeon

আমি দেখি আপনি টার্মিয়াল করছেন: সত্য। ওটার মানে কি? আমি কি এই নির্দেশাবলী পাশাপাশি ফর্মগুলিতে ব্যবহার করতে পারি <form ng-repeat="item in items" dynamic-name="'item'+item.id"> ... <span ng-show="item{{item.id}}.$invalid">This form is invalid</span></form>?
felixfbecker

16

সমস্যা AngularJS 1.3 সংশোধন করা উচিত, এই আলোচনা অনুযায়ী গিটহাব

এদিকে, @ ক্যাটপ এবং @ থিংসকেপ দ্বারা তৈরি করা একটি অস্থায়ী সমাধান :

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

জেএসফিডেলে ডেমো ।


4
এনজিও ১.২ এ আটকে রয়েছে তাদের পক্ষে এটি খুব সহজেই 'হ্যাকি' ফিক্স।
গ্রেনেড

14

@EnISeeK এর মাধ্যমে খুব সুন্দর .... তবে আমি এটি আরও মার্জিত এবং অন্যান্য নির্দেশের প্রতি কম বাধা হয়ে উঠতে পেরেছি:

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

4
আমি কেবল নিম্নলিখিতগুলি যুক্ত করব। ctrls [0]। $ নাম = সুযোগ। $ ইভাল (attrs.dynamicName) || attrs.dynamicName;
GnrlBzik

7

এনলিজিক সমাধানের তুলনায় সামান্য উন্নতি

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

  };
}]);

এখানে একটি প্লাঙ্কার ট্রায়ালএখানে বিস্তারিত ব্যাখ্যা দেওয়া আছে


+1, এঞ্জেলিকের নির্দেশনাটি আমার নির্দেশনায় অসীম লুপ সৃষ্টি করেছিল; এটির কাজটি পেতে আমাকে এই উত্তরের 'fx' টুকরো অপসারণ করতে হয়েছিল, যদিও
জন

অগ্রাধিকার ক্ষেত্রগুলির একটি সেটের সাথে হস্তক্ষেপ করতে পারে যা একই নাম ধরে নেওয়া হবে তবে এনজি-থাকলে। উদাহরণস্বরূপ: <ইনপুট টাইপ = 'পাঠ্য' গতিশীল-নাম = 'ফু' এনজি-ইফ = 'ফিল্ড.টাইপ == "পাঠ্য" /> <টেক্সারিয়া ডায়নামিক-নাম =' ফু 'এনজি-ইফ =' ফিল্ড.টাইপ == "টেক্সারিয়া"> </textarea> 'অগ্রাধিকার: 10000' সরানো আমার জন্য সমস্যার সমাধান করেছে এবং এখনও সঠিকভাবে কাজ করছে বলে মনে হচ্ছে।
দু'বার লিখে দিন

এনজিআইএফটির অগ্রাধিকার 600 রয়েছে। এই নির্দেশিকার জন্য 600 টিরও কম অগ্রাধিকার নির্ধারণ করুন এটি এনজিআইএফের সাথে একসাথে কাজ করা উচিত।
জেসন ঝাং

যদি কোনও অগ্রাধিকার সেট না করা থাকে (ডিফল্ট থেকে 0), এটি এনজিএমডেলের (অগ্রাধিকার 0) সাথে কাজ করতে পারে যদি এনজিএমডেলের আগে এই নির্দেশিকাটি মূল্যায়ন করা হয়। আপনি এটিকে অগ্রাধিকার দিতে চান যাতে এটি এনজিএমডেল সংকলিত / সংযুক্ত হওয়ার আগে সর্বদা থাকে is
জেসন ঝাং

5

আমি গতিশীলভাবে তৈরি নেস্টেড এনজি-ফর্মগুলিকে এই জাতীয় মঞ্জুরি দেওয়ার জন্য @ ক্যাটপ এবং @ থিংসক্যাপ সমাধানটি কিছুটা প্রসারিত করেছি :

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

জেএসফিডেলে আমার ডেমোটি এখানে ।


4

আমি বেন লেশের সমাধানটি ব্যবহার করেছি এবং এটি আমার পক্ষে ভাল কাজ করে। তবে একটি সমস্যার মুখোমুখি হ'ল আমি যখন ব্যবহার করে অভ্যন্তরীণ ফর্ম যুক্ত করেছি, তখন ফর্মের ng-formসমস্ত রাজ্যগুলি উদাহরণস্বরূপ, form.$valid, form.$errorআমি যদি 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
}

আমি কেন এটি নিশ্চিত তা নিশ্চিত নই তবে আশা করি এটি কারও সহায়ক।


3

এই সমস্যাটি কৌনিক 1.3+ এ স্থির করা হয়েছে আপনি যা করতে চেষ্টা করছেন এটির জন্য এটি সঠিক বাক্য গঠন:

login[input.name].$invalid

0

যদি আমরা নীচের মত একটি ইনপুট জন্য গতিশীল নাম সেট করে

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

তারপরে আমরা নীচের কোডের মতো গতিশীল নামের জন্য সেট বৈধতা ব্যবহার করেছি।

<div ng-messages="login.dynamicInputName.$error">
   <div ng-message="required">
   </div>
</div>
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.