Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to update secondary signal when input signal changes #54985

Closed
RaederDev opened this issue Mar 21, 2024 · 3 comments
Closed

Add ability to update secondary signal when input signal changes #54985

RaederDev opened this issue Mar 21, 2024 · 3 comments

Comments

@RaederDev
Copy link

Which @angular/* package(s) are relevant/related to the feature request?

core

Description

I have created a "multi select" component where a user can select any number of choices from a given list. This list is added to the component with an input signal. The selected options are stored in a WritableSignal as the user selects them. If the list of choices is updated from outside the component by the template embedding it the list of selected values need to be reset. I have not found a good way of doing this with signals whereas this was easily possible with ngOnChanges and the old @Input decorator.

The documentation warns against writing to signals in an effect so using an effect to do this does not seem like the best idea.

@Component({
  selector: 'app-multi-select-group',
  templateUrl: './multi-select-group.component.html',
})
export class MultiSelectGroupComponent {
  // issue is here
  public options = input<Array<MultiSelectGroupOption>>([]); // <- when this changes selectedItems needs to be reset
  public selectedItems = signal<Array<MultiSelectGroupOption>>([]);

  @Output() // ignore that I'm using the old API here Webstorm cannot deal with output signals properly yet
  public selectionChange = new EventEmitter<Array<MultiSelectGroupOption>>();

  public constructor() {
    effect(() => {
      this.selectionChange.emit(this.selectedItems());
    });
  }

  public selectItem(item: MultiSelectGroupOption): void {
      this.selectedItems.set([...selectedItems, item]);
  }
}

Proposed solution

Add an option to the input signal to specify a function that can do writes to other signals once the component input changes.

Alternatives considered

The alternative I could think of would be a adding a way to completely reset a component once a specific input signal changes.

@RobbyRabbitman
Copy link

You can write to signals in an effect without error, if you opt out the reactive context by wrapping the setting of the signal with untracked().

// somewhere in your effect
untracked(() => mySignal.set(newValue))

@RaederDev
Copy link
Author

Thank you! That seems to work fine without causing issues.

public constructor() {
    let prevOptions: Array<MultiSelectGroupOption> = [];

    effect(() => {
      const options = this.options();
      untracked(() => {
        if (prevOptions !== options) {
          prevOptions = options;
          this.selectedItems.set([]);
        }
      });
      this.selectionChange.emit(this.selectedItems());
    });
  }

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Apr 21, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants