কৌণিকের ফর্ম পরিবর্তনের জন্য কীভাবে দেখুন


151

কৌণিক ভাষায়, আমার কাছে এমন একটি ফর্ম থাকতে পারে যা দেখতে দেখতে:

<ng-form>
    <label>First Name</label>
    <input type="text" ng-model="model.first_name">

    <label>Last Name</label>
    <input type="text" ng-model="model.last_name">
</ng-form>

সংশ্লিষ্ট নিয়ামকের মধ্যে, আমি সহজেই ফর্মের সামগ্রীতে পরিবর্তনের জন্য দেখতে পেতাম:

function($scope) {

    $scope.model = {};

    $scope.$watch('model', () => {
        // Model has updated
    }, true);

}

এখানে জেএসফিডেলের একটি কৌনিক উদাহরণ রয়েছে

কৌণিকর ক্ষেত্রে কীভাবে একই জিনিসটি সম্পাদন করা যায় তা বুঝতে আমার সমস্যা হচ্ছে। স্পষ্টতই, আমাদের আর নেই $scope, S রুটস্কোপ। অবশ্যই একটি পদ্ধতি আছে যার দ্বারা একই জিনিস সম্পাদন করা যায়?

এখানে প্লাঙ্কারের একটি কৌনিক উদাহরণ রয়েছে


আপনার নিয়ামকের কাছ থেকে কিছু ডেটা দেখার পরিবর্তে, আমি মনে করি আপনার ফর্মটি থেকে কোনও ইভেন্ট (পুরানো এনজি-চেঞ্জের মতো) গুলি চালানো উচিত।
দেবলটন জিন-ফিলিপ

বিটিডব্লিউ, সুযোগটি সরানোর কারণ হ'ল এই পর্যবেক্ষকদের থেকে মুক্তি পাওয়া। আমি মনে করি না কৌনিক 2 এ কোথাও কোনও ঘড়ি লুকিয়ে আছে
দেবলটন জ্যান-ফিলিপ

4
যদি আমি আপনাকে সঠিকভাবে বুঝতে পারি তবে আপনি পরামর্শ দিচ্ছেন যে এটি সম্পাদন করার জন্য আমি প্রতিটি ফর্ম ইনপুটটিতে একটি (ngModelChange)="onModelChange($event)"গুণ যুক্ত করব ?
তামিলার

1
ফর্ম উদাহরণটি নিজেই কি কোনও ধরণের পরিবর্তনের ইভেন্ট নির্গত হয় না? যদি তা হয় তবে কীভাবে আপনি এটি অ্যাক্সেস করবেন?
তামিলার

আমি যদি করণীয় সম্পর্কে নিশ্চিত হয়ে থাকি তবে আমি মন্তব্য করার পরিবর্তে উত্তর জানতাম। আমি এখনও কৌনিক 2.0 ব্যবহার করি নি, তবে আমি যা পড়েছি তা থেকে, ইভেন্টটি ভিত্তিক কাঠামো (প্রতিটি ডাইজেস্টে গভীর ঘড়ির পরিবর্তে) পুরোপুরি অদৃশ্য হয়ে গেছে
দেবলটন জিন-ফিলিপ

উত্তর:


189

UPD। উত্তর এবং ডেমো সর্বশেষ কৌণিকের সাথে সারিবদ্ধ করার জন্য আপডেট করা হয়েছে।


ফর্মগ্রুপ একটি ফর্ম প্রতিনিধিত্ব করে এমন valueChangesসম্পত্তি সরবরাহ করে যা পর্যবেক্ষণযোগ্য উদাহরণ হিসাবে এই কারণে আপনি পুরো ফর্ম পরিবর্তনের জন্য সাবস্ক্রাইব করতে পারেন :

this.form.valueChanges.subscribe(data => console.log('Form changes', data));

এই ক্ষেত্রে আপনাকে ফর্মবিল্ডার ব্যবহার করে ম্যানুয়ালি ফর্ম তৈরি করতে হবে । এটার মতো কিছু:

export class App {
  constructor(private formBuilder: FormBuilder) {
    this.form = formBuilder.group({
      firstName: 'Thomas',
      lastName: 'Mann'
    })

    this.form.valueChanges.subscribe(data => {
      console.log('Form changes', data)
      this.output = data
    })
  }
}

valueChangesএই ডেমোটিতে ক্রিয়াকলাপ পরীক্ষা করে দেখুন : http://plnkr.co/edit/xOz5xaQyMlRzSrgtt7Wn?p=preview


2
এটি চিহ্নের খুব কাছাকাছি। নিশ্চিত করার জন্য - আপনি কি আমাকে বলছেন যে কোনও ফর্মটি কেবলমাত্র টেমপ্লেটের মধ্যেই সংজ্ঞায়িত করা হলে কোনও ফর্মের ইভেন্ট ইমিটারে সদস্যতা নেওয়া সম্ভব নয় ? অন্য কথায় - কোনও উপাদানগুলির নির্মাতার মধ্যে, ফর্মবিল্ডারের সাহায্যে নয়, কেবলমাত্র সেই উপাদানটির টেমপ্লেটের মধ্যেই সংজ্ঞায়িত কোনও ফর্মের রেফারেন্স পাওয়া সম্ভব নয়? valueChanges
টেবল্লার

এই সঠিক উত্তর। যদি আপনার কাছে ফর্ম নির্মাতা না থাকে তবে আপনি টেম্পলেট চালিত ফর্মগুলি করছেন। সেখানে সম্ভবত একটি উপায় এখনও ফর্ম ইনজেকশনের কিন্তু আপনি যদি পর্যবেক্ষণযোগ্য form.valueChanges চাই নিশ্চিতভাবেই formBuilder ব্যবহার এবং পরিত্যাগ NG-মডেল উচিত পেতে হয়
কৌণিক বিশ্ববিদ্যালয়ের

2
@ টমবলার, আপনি এনজিএফর্ম ব্যবহার করে একটি রেফারেন্স পেতে পারেন @ViewChild()। আমার আপডেট হওয়া উত্তরটি দেখুন।
রাজকোক

1
আপনি ধ্বংস উপর সাবস্ক্রাইব প্রয়োজন হবে না?
বাজিঙ্গা

1
@ বাগওয়ান আমার মনে হয় না যে এখানে কোনও ফুটো হতে পারে। ফর্মটি উপাদানটির অংশ এবং এটি এর ক্ষেত্র এবং ইভেন্ট শ্রোতার সাথে ধ্বংসের বিরুদ্ধে যথাযথভাবে নিষ্পত্তি করা হবে।
dfsq

107

আপনি যদি ব্যবহার করছেন তবে FormBuilder@ ডিএফএসকিউর উত্তর দেখুন।

আপনি যদি ব্যবহার না করে থাকেন FormBuilderতবে পরিবর্তনের বিষয়ে অবহিত হওয়ার দুটি উপায় রয়েছে।

পদ্ধতি 1

প্রশ্নের মন্তব্যে আলোচিত হিসাবে, প্রতিটি ইনপুট উপাদানকে বাধ্যতামূলকভাবে একটি ইভেন্ট ব্যবহার করুন। আপনার টেমপ্লেটে যুক্ত করুন:

<input type="text" class="form-control" required [ngModel]="model.first_name"
         (ngModelChange)="doSomething($event)">

তারপরে আপনার উপাদানগুলিতে:

doSomething(newValue) {
  model.first_name = newValue;
  console.log(newValue)
}

ফরম পৃষ্ঠা ngModel সম্পর্কে কিছু অতিরিক্ত তথ্য যে এখানে প্রাসঙ্গিক আছে:

ngModelChangeএকটি নয় <input>উপাদান ইভেন্ট। এটি আসলে NgModelনির্দেশের একটি ইভেন্ট সম্পত্তি । যখন কৌনিকটি ফর্মটিতে একটি বাধ্যতামূলক লক্ষ্য দেখে [(x)], xনির্দেশটি একটি xইনপুট সম্পত্তি এবং xChangeআউটপুট সম্পত্তি থাকার প্রত্যাশা করে ।

অন্যান্য বিজোড়তা হ'ল টেমপ্লেট এক্সপ্রেশন model.name = $event,। আমরা $eventকোনও ডিওএম ইভেন্ট থেকে আসা কোনও জিনিস দেখার অভ্যস্ত। NgModelChange বৈশিষ্ট্যটি কোনও DOM ইভেন্ট তৈরি করে না; এটি একটি কৌণিক EventEmitterসম্পত্তি যা আগুনের সময় ইনপুট বাক্সের মান প্রদান করে ..

আমরা প্রায় সবসময় পছন্দ [(ngModel)]। আমরা ইভেন্ট হ্যান্ডলিং যেমন কী স্ট্রোক ডাবনো বা থ্রোটলের মতো বিশেষ কিছু করতে হত তবে আমরা বাইন্ডিংটিকে বিভক্ত করতে পারি।

আপনার ক্ষেত্রে, আমি মনে করি আপনি বিশেষ কিছু করতে চান।

পদ্ধতি 2

একটি স্থানীয় টেমপ্লেট পরিবর্তনশীল নির্ধারণ করুন এবং এটি সেট ngForm
ইনপুট উপাদানগুলিতে ngControl ব্যবহার করুন।
@ ভিউচিল্ড ব্যবহার করে ফর্মের এনজিএফর্মের নির্দেশনার একটি রেফারেন্স পান, তারপরে পরিবর্তনের জন্য এনজিএফর্মের কন্ট্রোলগ্রুপটিতে সাবস্ক্রাইব করুন:

<form #myForm="ngForm" (ngSubmit)="onSubmit()">
  ....
  <input type="text" ngControl="firstName" class="form-control" 
   required [(ngModel)]="model.first_name">
  ...
  <input type="text" ngControl="lastName" class="form-control" 
   required [(ngModel)]="model.last_name">

class MyForm {
  @ViewChild('myForm') form;
  ...
  ngAfterViewInit() {
    console.log(this.form)
    this.form.control.valueChanges
      .subscribe(values => this.doSomething(values));
  }
  doSomething(values) {
    console.log(values);
  }
}

plunker

পদ্ধতি 2 সম্পর্কিত আরও তথ্যের জন্য, সাবকিনের ভিডিও দেখুন

valueChangesপর্যবেক্ষণযোগ্যদের সাথে আপনি কী করতে পারেন সে সম্পর্কে আরও তথ্যের জন্য @ থিয়েরির উত্তরও দেখুন (যেমন পরিবর্তনগুলি প্রক্রিয়া করার আগে কিছুটা প্রত্যাখ্যান / অপেক্ষা করা)।


61

আরও কিছু আগের দুর্দান্ত উত্তরগুলি সম্পূর্ণ করতে, আপনাকে সচেতন হওয়া দরকার যে মান পরিবর্তনগুলি সনাক্ত করতে এবং পরিচালনা করতে লিভারেজ অবজার্ভেবলগুলি তৈরি করে। এটি সত্যই গুরুত্বপূর্ণ এবং শক্তিশালী কিছু। মার্ক এবং ডিএফএসকিউ উভয়ই তাদের উত্তরে এই দিকটি বর্ণনা করেছেন।

পর্যবেক্ষণযোগ্যরা কেবল subscribeপদ্ধতিটি ব্যবহার করতে পারবেন না ( thenকৌনিক 1 এ প্রতিশ্রুতির পদ্ধতির অনুরূপ কিছু )। ফর্মগুলিতে আপডেট হওয়া ডেটার জন্য কিছু প্রসেসিং চেইন প্রয়োগ করার প্রয়োজন হলে আপনি আরও যেতে পারেন।

মানে আপনি এই স্তরে debounceTimeপদ্ধতিটির সাথে আত্মপ্রকাশের সময়টি নির্দিষ্ট করতে পারেন । এটি আপনাকে পরিবর্তনটি পরিচালনা করার আগে বেশ কিছু সময়ের জন্য অপেক্ষা করতে এবং বেশ কয়েকটি ইনপুট সঠিকভাবে পরিচালনা করতে দেয়:

this.form.valueChanges
    .debounceTime(500)
    .subscribe(data => console.log('form changes', data));

মানগুলি আপডেট হয়ে গেলে আপনি সরাসরি প্রসেসিংটি প্লাগ করতে পারেন যা আপনি ট্রিগার করতে চান (উদাহরণস্বরূপ কিছু অ্যাসিনক্রোনাস এক)। উদাহরণস্বরূপ, আপনি যদি এজেএক্স অনুরোধের ভিত্তিতে একটি তালিকা ফিল্টার করতে কোনও পাঠ্য মানটি পরিচালনা করতে চান তবে আপনি এই switchMapপদ্ধতিটি উপকার করতে পারবেন :

this.textValue.valueChanges
    .debounceTime(500)
    .switchMap(data => this.httpService.getListValues(data))
    .subscribe(data => console.log('new list values', data));

এমনকি প্রত্যক্ষিত পর্যবেক্ষণযোগ্যকে সরাসরি আপনার উপাদানগুলির কোনও সংস্থার সাথে সংযুক্ত করে আপনি আরও এগিয়ে যান:

this.list = this.textValue.valueChanges
    .debounceTime(500)
    .switchMap(data => this.httpService.getListValues(data))
    .subscribe(data => console.log('new list values', data));

এবং asyncপাইপ ব্যবহার করে এটি প্রদর্শন করুন :

<ul>
  <li *ngFor="#elt of (list | async)">{{elt.name}}</li>
</ul>

কেবল এটি বলার জন্য আপনাকে Angular2 (অন্যরকম শক্তিশালী উপায় ;-)) থেকে ফর্মগুলি হ্যান্ডেল করার উপায়টি ভাবতে হবে।

আশা করি এটি আপনাকে সাহায্য করবে, থিয়েরি


প্রকার 'মান' পরিবর্তনগুলি 'স্ট্রিং' টাইপটিতে বিদ্যমান নেই
টুলকিট

আমি আটকে গিয়েছি, টিএস ফাইলে, চেক ফর্ম পরিবর্তন পদ্ধতিটি কোথায় রাখা উচিত? আমরা যদি এটি এনজিএফটারভিউআইনিট () in in এ সঞ্চয় করি তবে মনে হয় যে আমাদের.ফর্ম.ভালিউচেনামগুলি ফর্মগুলিতে আপডেট হওয়া ডেটার জন্য কিছু প্রসেসিং চেইন প্রয়োগ করার প্রয়োজন হলে সর্বদা কল করে।
T Ni Nguyễn

1

মার্কের পরামর্শগুলিতে সম্প্রসারণ করা হচ্ছে ...

পদ্ধতি 3

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

export class App implements DoCheck {
  person = { first: "Sally", last: "Jones" };
  oldPerson = { ...this.person }; // ES6 shallow clone. Use lodash or something for deep cloning

  ngDoCheck() {
    // Simple shallow property comparison - use fancy recursive deep comparison for more complex needs
    for (let prop in this.person) {
      if (this.oldPerson[prop] !==  this.person[prop]) {
        console.log(`person.${prop} changed: ${this.person[prop]}`);
        this.oldPerson[prop] = this.person[prop];
      }
    }
  }

প্লাঙ্কারে চেষ্টা করুন


1

কৌণিক 5+সংস্করণ জন্য। কৌণিক অনেক পরিবর্তন আনায় সংস্করণে রাখার সাহায্য করে।

ngOnInit() {

 this.myForm = formBuilder.group({
      firstName: 'Thomas',
      lastName: 'Mann'
    })
this.formControlValueChanged() // Note if you are doing an edit/fetching data from an observer this must be called only after your form is properly initialized otherwise you will get error.
}

formControlValueChanged(): void {       
        this.myForm.valueChanges.subscribe(value => {
            console.log('value changed', value)
        })
}

0

আমি (এনজিএমডেল চ্যাঞ্জ) পদ্ধতিটি ব্যবহার করার বিষয়ে ভাবলাম, তারপরে ফর্মবিল্ডার পদ্ধতিটি নিয়ে ভাবলাম এবং অবশেষে পদ্ধতি 3 এর পরিবর্তনে স্থির হয়ে গেলাম extra পদ্ধতি 1 বা 2 দিয়ে।

সরলকরণ পদ্ধতি 3 একটি বিট ...

oldPerson = JSON.parse(JSON.stringify(this.person));

ngDoCheck(): void {
    if (JSON.stringify(this.person) !== JSON.stringify(this.oldPerson)) {
        this.doSomething();
        this.oldPerson = JSON.parse(JSON.stringify(this.person));
    }
}

ডাবনউস অনুকরণের জন্য x সংখ্যার মিলি সেকেন্ডের পরে আপনি কেবল ডোসোমথিং () কল করতে একটি সময়সীমা যুক্ত করতে পারেন।

oldPerson = JSON.parse(JSON.stringify(this.person));

ngDoCheck(): void {
    if (JSON.stringify(this.person) !== JSON.stringify(this.oldPerson)) {
        if (timeOut) clearTimeout(timeOut);
        let timeOut = setTimeout(this.doSomething(), 2000);
        this.oldPerson = JSON.parse(JSON.stringify(this.person));
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.