যখন একটি কৌনিকটিতে একটি @ ইনপুট () মান পরিবর্তন হয় তখন কীভাবে সনাক্ত করবেন?


468

আমার একটি পিতা-মাতা উপাদান ( বিভাগের উপাদান ), একটি শিশু উপাদান ( ভিডিওলিস্ট কম্পোনেন্ট ) এবং একটি এপি-সার্ভিস রয়েছে।

আমার বেশিরভাগ এই কাজ করা সূক্ষ্ম অর্থাত্ প্রতিটি উপাদান জসন এপিআই অ্যাক্সেস করতে পারে এবং পর্যবেক্ষণের মাধ্যমে তার সম্পর্কিত ডেটা পেতে পারি।

বর্তমানে ভিডিও তালিকার উপাদানটি কেবলমাত্র সমস্ত ভিডিও পেয়েছে, আমি এটি একটি নির্দিষ্ট বিভাগের কেবলমাত্র ভিডিওগুলিতে ফিল্টার করতে চাই, আমি এই বিভাগটি আইডির মাধ্যমে সন্তানের কাছে পাস করে অর্জন করেছি @Input()

CategoryComponent.html

<video-list *ngIf="category" [categoryId]="category.id"></video-list>

এটি কাজ করে এবং যখন প্যারেন্ট ক্যাটাগরি @Input()কম্পোনেন্ট বিভাগটি পরিবর্তিত হয় তখন বিভাগ আইড মানটি এর মধ্য দিয়ে যেতে পারে তবে আমার তখন এটি ভিডিওলিস্টকম্পোন্টে সনাক্ত করতে হবে এবং এপিআইএসওয়্যারের মাধ্যমে নতুন অ্যারে ভিডিওর অ্যারে পুনরায় অনুরোধ করতে হবে (নতুন বিভাগে আইডি সহ)।

AngularJS এ আমি $watchভেরিয়েবলটি করতে পারতাম done এই হ্যান্ডেল করার সেরা উপায় কি?



-: ইনপুট পরিবর্তন ঘড়ি angulartutorial.net/2017/12/watch-input-changes-angular-4.html
Prashobh

: অ্যারের পরিবর্তনের জন্য stackoverflow.com/questions/42962394/...
dasfdsa

উত্তর:


717

প্রকৃতপক্ষে, কৌনিক 2 + এ যখন কোনও উপাদান ইনপুট পরিবর্তিত হয় তখন সনাক্তকরণ এবং অভিনয় করার দুটি উপায় রয়েছে:

  1. আপনি পুরানো উত্তরে উল্লিখিত হিসাবে এনজিওনচেন্জেস () জীবনচক্র পদ্ধতিটি ব্যবহার করতে পারেন :
    @Input() categoryId: string;

    ngOnChanges(changes: SimpleChanges) {

        this.doSomething(changes.categoryId.currentValue);
        // You can also use categoryId.previousValue and 
        // categoryId.firstChange for comparing old and new values

    }

ডকুমেন্টেশন লিংক: এনজিচেনজেস, সিম্পল চেঞ্জস, সিম্পল চেঞ্জ
ডেমো উদাহরণ: এই নিমজ্জনকারীকে দেখুন

  1. পর্যায়ক্রমে, আপনি নিম্নলিখিত হিসাবে একটি ইনপুট সম্পত্তি সেটার ব্যবহার করতে পারেন :
    private _categoryId: string;

    @Input() set categoryId(value: string) {

       this._categoryId = value;
       this.doSomething(this._categoryId);

    }

    get categoryId(): string {

        return this._categoryId;

    }

ডকুমেন্টেশন লিঙ্ক: এখানে দেখুন

ডেমো উদাহরণ: এই নিমজ্জনকারী দেখুন

আপনি কী ব্যবহার করবেন?

যদি আপনার উপাদানটির বেশ কয়েকটি ইনপুট থাকে, তবে আপনি যদি এনজিওনচেঞ্জস () ব্যবহার করেন তবে আপনি সমস্ত ইনপুটগুলির জন্য একবারে এনজিওচেনজেস () এর মধ্যে সমস্ত পরিবর্তনগুলি পাবেন। এই পদ্ধতির ব্যবহার করে, আপনি পরিবর্তিত ইনপুটটির বর্তমান এবং পূর্ববর্তী মানগুলিও তুলনা করতে পারেন এবং সেই অনুসারে পদক্ষেপ নিতে পারেন।

যাইহোক, যদি আপনি কিছু করতে চান যখন কেবলমাত্র একটি নির্দিষ্ট একক ইনপুট পরিবর্তন হয় (এবং আপনি অন্যান্য ইনপুটগুলির বিষয়ে চিন্তা করেন না) তবে কোনও ইনপুট সম্পত্তি সেটার ব্যবহার করা সহজ। যাইহোক, এই পদ্ধতির পরিবর্তিত ইনপুটটির পূর্বের এবং বর্তমান মানগুলির তুলনা করার জন্য একটি অন্তর্নির্মিত সরবরাহ সরবরাহ করা হয় না (যা আপনি সহজেই এনজিওনচেঞ্জস লাইফাইসাইকেল পদ্ধতির সাহায্যে করতে পারেন)।

সম্পাদনা করুন 2017-07-25: অ্যাঙ্গুলার পরিবর্তন সম্পর্কিত তথ্য হয়তো কিছু সরু দাসের মধ্যে আগুন নেবে না

সাধারনত, সেটার এবং এনজিওনচ্যাঞ্জস উভয়ের জন্য সনাক্তকরণের পরিবর্তনটি যখনই পিতা বা মাতা উপাদানটি সন্তানের কাছে যায় সেই ডেটা পরিবর্তন করে, তবে শর্ত থাকে যে ডেটাটি জেএস আদিম ডেটাটাইপ (স্ট্রিং, সংখ্যা, বুলিয়ান) । তবে, নিম্নলিখিত পরিস্থিতিতে, এটি জ্বলবে না এবং এটিকে কাজ করতে আপনাকে অতিরিক্ত পদক্ষেপ নিতে হবে।

  1. আপনি যদি কোনও নেস্টেড অবজেক্ট বা অ্যারে ব্যবহার করেন (জেএস আদিম ডাটা টাইপের পরিবর্তে) পিতামাতাদের কাছ থেকে সন্তানের কাছে ডেটা পাস করার জন্য, সনাক্তকরণ পরিবর্তন করুন (সেটার বা এনজিচেঞ্জ ব্যবহার করে) অগ্নিকাণ্ডে না আসতে পারে, যেমনটি ব্যবহারকারীর উত্তরে বর্ণিত হয়েছে: মুটিজারিচ। সমাধানের জন্য এখানে দেখুন ।

  2. যদি আপনি কৌণিক প্রসঙ্গে (যেমন, বাহ্যিকভাবে) বাইরে ডেটা পরিবর্তন করে থাকেন তবে কৌণিক পরিবর্তনগুলি জানতে পারবেন না। বাহ্যিক পরিবর্তন সম্পর্কে কৌণিক সচেতন করতে এবং এর ফলে পরিবর্তন সনাক্তকরণকে ট্রিগার করতে আপনাকে আপনার উপাদানটিতে চেঞ্জডেক্টরআরফ বা এনজিওন ব্যবহার করতে হতে পারে। পড়ুন এই


8
ইনপুট সহ সেটারগুলি ব্যবহার সম্পর্কে খুব ভাল পয়েন্ট, আমি এটি আরও ব্যাপক হিসাবে গ্রহণযোগ্য উত্তর হিসাবে এটি আপডেট করব। ধন্যবাদ।
জন ক্যাটমুল

2
@ ত্রিচেত্রিচি, যখনই পিতামাতারা ইনপুট পরিবর্তন করে তখন সেটার (সেট পদ্ধতি) কল হবে। এছাড়াও, একইভাবে এনজিওচেনজ () এর ক্ষেত্রেও এটি সত্য।
অ্যালান সিএস

আপাতদৃষ্টিতে ভাল নয় ... আমি এটি বের করার চেষ্টা করব, এটি সম্ভবত আমি কিছু ভুল করেছি।

1
আমি এই প্রশ্নটি নিয়ে কেবলই হোঁচট খেয়েছি, উল্লেখ করেছি যে আপনি বলেছেন যে সেটারটি ব্যবহার করে মানগুলির তুলনা করা যাবে না, তবে এটি সত্য নয়, আপনি নিজের doSomethingপদ্ধতিটি কল করতে পারেন এবং নতুন যুক্তিটি নতুন ও পুরানো মানগুলি গ্রহণ করতে পারবেন , অন্যভাবে সেটিংস স্থাপনের আগে এবং তার পরে পদ্ধতিটি কল করার আগে পুরানো মানটি সংরক্ষণ করা হবে।
টি.অউকার

1
@ টি.আউকার আমি যা বলছি তা হ'ল ইনপুট সেটার স্থানীয়ভাবে পুরানো / নতুন মানগুলিকে এনজিওচেনজেস () এর সাথে তুলনা করতে সমর্থন করে না। আপনি পুরানো মান সংরক্ষণ করার জন্য সর্বদা হ্যাক ব্যবহার করতে পারেন (যেমন আপনি উল্লেখ করেছেন) এটি নতুন মানের সাথে তুলনা করতে।
অ্যালান সিএস

105

ngOnChanges()আপনার উপাদানটিতে লাইফাইসাইকেল পদ্ধতিটি ব্যবহার করুন ।

ngOnChanges ডানদিকে আবদ্ধ বৈশিষ্ট্যগুলি যাচাই করার পরে এবং শিশুদের অন্ততপক্ষে কোনও একটি পরিবর্তন হয়েছে কিনা তা পরীক্ষা করার আগে ডাকা হয় checked

এখানে ডক্স রয়েছে


6
ভেরিয়েবলটি যখন একটি নতুন মান যেমন সেট করা থাকে তবে এটি কাজ করে MyComponent.myArray = [], তবে যদি কোনও ইনপুট মান পরিবর্তিত হয় MyComponent.myArray.push(newValue), ngOnChanges()ট্রিগার হয় না। এই পরিবর্তনটি কীভাবে ধরা যায় সে সম্পর্কে কোনও ধারণা?
লেভি ফুলার

4
ngOnChanges()কোনও নেস্টেড বস্তু পরিবর্তিত হলে তাকে ডাকা হয় না। সম্ভবত আপনি এখানে
মুটিজারিচ

33

SimpleChangesফাংশন স্বাক্ষরে টাইপটি ব্যবহার করার সময় আমি কনসোলের পাশাপাশি সংকলক এবং আইডিইতে ত্রুটি পেয়েছি । ত্রুটিগুলি রোধ করতে anyপরিবর্তে স্বাক্ষরে কীওয়ার্ডটি ব্যবহার করুন ।

ngOnChanges(changes: any) {
    console.log(changes.myInput.currentValue);
}

সম্পাদনা করুন:

জনের নীচের দিকে ইঙ্গিত হিসাবে, আপনি SimpleChangesবিন্দু চিহ্নিতকরণের চেয়ে বন্ধনী স্বরলিপি ব্যবহার করার সময় স্বাক্ষরটি ব্যবহার করতে পারেন ।

ngOnChanges(changes: SimpleChanges) {
    console.log(changes['myInput'].currentValue);
}

1
আপনি কি SimpleChangesআপনার ফাইলের শীর্ষে ইন্টারফেসটি আমদানি করেছেন ?
জন ক্যাটমুল

@ জন - হ্যাঁ সমস্যাটি স্বাক্ষরটি নিজেই ছিল না, তবে রানটাইম সময়ে সিম্পল চেঞ্জস অবজেক্টে নির্ধারিত পরামিতিগুলি অ্যাক্সেস করা। উদাহরণস্বরূপ, আমার উপাদানটিতে আমি আমার ব্যবহারকারীর শ্রেণিটিকে ইনপুট (ie <my-user-details [user]="selectedUser"></my-user-details>) দিয়ে আবদ্ধ করেছি । এই সম্পত্তিটি কল করে সিম্পল চেঞ্জস শ্রেণি থেকে অ্যাক্সেস করা হয়েছে changes.user.currentValue। নোটিশ userরানটাইমে আবদ্ধ এবং সিম্পল চেঞ্জস অবজেক্টের অংশ নয়
ডারসি

1
আপনি কি এই চেষ্টা করেছেন? ngOnChanges(changes: {[propName: string]: SimpleChange}) { console.log('onChanges - myProp = ' + changes['myProp'].currentValue); }
জন ক্যাটমুল

@ জন - বন্ধনী স্বরলিপিতে স্যুইচ করা কৌশলটি কার্যকর করে। বিকল্প হিসাবে অন্তর্ভুক্ত করার জন্য আমি আমার উত্তর আপডেট করেছি।
ডারসি

1
'@ কৌণিক / কোর' থেকে import সিম্পল চেঞ্জস import আমদানি করুন; যদি এটি কৌণিক ডক্সে থাকে এবং কোনও দেশীয় টাইপস্ক্রিপ্ট টাইপ না হয় তবে সম্ভবত এটি একটি কৌণিক মডিউল থেকে সম্ভবত সম্ভবত 'কৌণিক / কোর'
বেন্টঅনকোডিং

13

সবচেয়ে নিরাপদ বাজি হ'ল প্যারামিটারের পরিবর্তে একটি ভাগ করা পরিষেবা নিয়ে @Input। এছাড়াও, @Inputপ্যারামিটার জটিল নেস্টেড অবজেক্টের ধরণের পরিবর্তনগুলি সনাক্ত করে না।

একটি সাধারণ উদাহরণ পরিষেবাটি নিম্নরূপ:

Service.ts

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';

@Injectable()
export class SyncService {

    private thread_id = new Subject<number>();
    thread_id$ = this.thread_id.asObservable();

    set_thread_id(thread_id: number) {
        this.thread_id.next(thread_id);
    }

}

Component.ts

export class ConsumerComponent implements OnInit {

  constructor(
    public sync: SyncService
  ) {
     this.sync.thread_id$.subscribe(thread_id => {
          **Process Value Updates Here**
      }
    }

  selectChat(thread_id: number) {  <--- How to update values
    this.sync.set_thread_id(thread_id);
  }
}

আপনি অন্যান্য উপাদানগুলিতে অনুরূপ বাস্তবায়ন ব্যবহার করতে পারেন এবং আপনার সমস্ত উপাদানগুলি একই ভাগ করা মানগুলি ভাগ করবে।


1
থানকিউ সংকেত। এটি তৈরি করার জন্য এটি একটি খুব ভাল পয়েন্ট এবং যেখানে এটি করার আরও ভাল উপায় appropriate আমি অনুমোদিত উত্তরটি ছেড়ে দেব কারণ এটি @ ইনপুট পরিবর্তনগুলি সনাক্তকরণ সম্পর্কিত আমার নির্দিষ্ট প্রশ্নের উত্তর হিসাবে দাঁড়ায়।
জন ক্যাটমুল

1
একটি @ ইনপুট প্যারামিটার একটি জটিল নেস্টেড অবজেক্টের ধরণের অভ্যন্তরের পরিবর্তনগুলি সনাক্ত করতে পারে না তবে যদি বস্তু নিজেই পরিবর্তিত হয় তবে তা আগুন ধরিয়ে দেবে, তাই না? উদাহরণস্বরূপ আমার ইনপুট প্যারামিটারটি "প্যারেন্ট" রয়েছে, সুতরাং আমি যদি সামগ্রিকভাবে পিতামাতাকে পরিবর্তন করি তবে পরিবর্তন সনাক্তকরণটি গুলি চালিত হবে, তবে আমি পিতামাতার নাম পরিবর্তন করলে তা হবে না?
যোগবিবিবি

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

1
@ জোশুয়া ক্যামেরার @Inputপ্যারামিটার জটিল নেস্টেড অবজেক্টের ধরণের পরিবর্তনগুলি সনাক্ত করতে পারে না তবে এটি সাধারণ নেটিভ অবজেক্টগুলিতে করে।
সংকেত বার্ডে

6

আমি কেবল যুক্ত করতে চাই যে আর একটি লাইফাইসাইকেল হুক বলা হয়েছে DoCheckযা দরকারী যদি @Inputমানটি কোনও আদিম মান না হয় useful

আমার হিসাবে একটি অ্যারে রয়েছে Inputযাতে OnChangesবিষয়বস্তু পরিবর্তিত হওয়ার পরে এটি ইভেন্টটিকে আগুন দেয় না (কারণ অ্যাংুলার যে পরীক্ষা করে তা 'সরল' এবং গভীর নয় তাই অ্যারেতে থাকা সামগ্রীর পরিবর্তন হওয়া সত্ত্বেও অ্যারে এখনও অ্যারে হয়)।

আমি তখন পরিবর্তিত অ্যারের সাথে আমার দৃষ্টিভঙ্গি আপডেট করতে চাই কিনা তা সিদ্ধান্ত নেওয়ার জন্য কিছু কাস্টম চেকিং কোড প্রয়োগ করি।


6
  @Input()
  public set categoryId(categoryId: number) {
      console.log(categoryId)
  }

এই পদ্ধতিটি ব্যবহার করার চেষ্টা করুন। আশাকরি এটা সাহায্য করবে


4

আপনি এমন একটি পর্যবেক্ষণযোগ্য থাকতেও পারেন যা প্যারেন্ট উপাদান (বিভাগের উপাদান) পরিবর্তনের জন্য ট্রিগার করে এবং আপনি সন্তানের উপাদানটিতে সাবস্ক্রিপশনে যা করতে চান তা করতে পারেন। (ভিডিওলিস্ট কম্পোনেন্ট)

service.ts 
public categoryChange$ : ReplaySubject<any> = new ReplaySubject(1);

-----------------
CategoryComponent.ts
public onCategoryChange(): void {
  service.categoryChange$.next();
}

-----------------
videoListComponent.ts
public ngOnInit(): void {
  service.categoryChange$.subscribe(() => {
   // do your logic
});
}

2

আপনার ইনপুট সম্পত্তি পরিবর্তিত হলে এখানে এনজিওনচেনজগুলি সর্বদা ট্রিগার করবে:

ngOnChanges(changes: SimpleChanges): void {
 console.log(changes.categoryId.currentValue)
}

1

এই সমাধানটি একটি প্রক্সি ক্লাস ব্যবহার করে এবং নিম্নলিখিত সুবিধাগুলি সরবরাহ করে:

  • গ্রাহককে আরএক্সজেএসের শক্তি অর্জনের অনুমতি দেয়
  • এখন পর্যন্ত প্রস্তাবিত অন্যান্য সমাধানের চেয়ে আরও কমপ্যাক্ট
  • ব্যবহারের চেয়ে বেশি টাইপসেফngOnChanges()

ব্যবহারের উদাহরণ:

@Input()
public num: number;
numChanges$ = observeProperty(this as MyComponent, 'num');

ইউটিলিটি ফাংশন:

export function observeProperty<T, K extends keyof T>(target: T, key: K) {
  const subject = new BehaviorSubject<T[K]>(target[key]);
  Object.defineProperty(target, key, {
    get(): T[K] { return subject.getValue(); },
    set(newValue: T[K]): void {
      if (newValue !== subject.getValue()) {
        subject.next(newValue);
      }
    }
  });
  return subject;
}

0

আপনি যদি এনজিওচেনজ ও ওএনচেঞ্জ () পদ্ধতিটি প্রয়োগ করতে না চান তবে আপনি মান আইকন ইভেন্টস , ইত্যাদি দ্বারা নির্দিষ্ট আইটেমের পরিবর্তনেরও সাবস্ক্রাইব করতে পারেন ।

 myForm= new FormGroup({
first: new FormControl()   

});

this.myForm.valueChanges.subscribe(formValue => {
  this.changeDetector.markForCheck();
});

এই ঘোষণায় ব্যবহারের কারণে মার্কফোরচেক () রাইটেন:

  changeDetection: ChangeDetectionStrategy.OnPush

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

0

আপনি কেবল ইনপুট হিসাবে একটি ইভেন্টইমিটার পাস করতে পারেন। এটি সর্বোত্তম অনুশীলন কিনা তা পুরোপুরি নিশ্চিত নয় ...

CategoryComponent.ts:

categoryIdEvent: EventEmitter<string> = new EventEmitter<>();

- OTHER CODE -

setCategoryId(id) {
 this.category.id = id;
 this.categoryIdEvent.emit(this.category.id);
}

CategoryComponent.html:

<video-list *ngIf="category" [categoryId]="categoryIdEvent"></video-list>

এবং ভিডিওলিস্ট কম্পোনেন্ট.স.

@Input() categoryIdEvent: EventEmitter<string>
....
ngOnInit() {
 this.categoryIdEvent.subscribe(newID => {
  this.categoryId = newID;
 }
}

আপনার সমাধানটি সমর্থন করার জন্য দয়া করে দরকারী লিঙ্কগুলি, কোড স্নিপেটগুলি সরবরাহ করুন।
মিশ্পসেক্স

আমি একটি উদাহরণ যুক্ত করেছি।
ক্যাড্রিক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.