Sergiu Molnar
Sergiu Molnar

Reputation: 1020

Change object property value without changing the reference

I'm working on a custom carrousel in an Angular app.

For each element in the carousel, the user can write a caption, but only one by one (for the selected element at the time).

enter image description here

So, what I did was to create only one input and to react on its event (input) and update the caption for the selected element as follows:

<input
matInput
formControlName="caption"
maxlength="500"
placeholder="Write caption"
(input)="onCaptionChanged($event?.target?.value)"
/>

onCaptionChanged(value: string) {
    this.galleryAttachments = this.galleryAttachments.map((x) =>
      x.attachment.id === this.selectedAttachment.id
        ? { ...x, attachment: { ...x.attachment, caption: value } }
        : x
    );
  }

It works fine but, by doing this

{ ...x, attachment: { ...x.attachment, caption: value } }

the object reference is changed which leads to flickering on the interface.

I also tried to get the selected element and to update its property value, like this:

const current = this.galleryAttachments.find(x => x.attachment.id === this.selectedAttachment.id);
current.attachment.caption = value;

but Angular throws the Cannot assign to read-only property error.

Is there a possibility to change an object property value without changing the object reference?

Or what should I do to avoid the flickering?

Upvotes: 0

Views: 1146

Answers (1)

TotallyNewb
TotallyNewb

Reputation: 4790

While you can definitely "hack around" it, the question you should ask yourself is not "How can I do it" but rather "Why should I do it?".

The author of the class you're trying to change definitely had a reason to mark this property as a read only. If that's your proprietary code - change the property to NOT be read only (and handle all changes that it causes). If it's not - perhaps you should either contact the author, change the library to a different one, or write the feature yourself?

The thing is, while it might work NOW it might NOT work after a future update of either Angular or the library. And this will cause much more problems later on.

And to answer your question (how to "hack around" it) - remember that TypeScript is, after all, superset of EcmaScript. So you can use the bracket notation to access any property of the object - and TypeScript will not know the attributes of that property, hence it will not throw an exception.

const current = this.galleryAttachments.find(x => x.attachment.id === this.selectedAttachment.id);
current.attachment['caption'] = value;

Upvotes: 1

Related Questions