0

In the following mock-up I use a signal as an input to a component. It works. But I am wondering if this is the proper use of a signal. Seems....weird.

The follwing is a service that maintains a list of My Friends:

import {
  Injectable,
  signal
} from '@angular/core';

export interface MyFriend {
  name: string;
  age: number;
}

@Injectable({
  providedIn: 'root'
})
export class MyFriendsService {
  myFriends = signal < MyFriend[] > ([{
      name: 'Bob',
      age: 34,
    },
    {
      name: 'Julie',
      age: 30,
    },
    {
      name: 'Martin',
      age: 25,
    },
  ]);
}

The folowing is a Friend Detail Component that shows the detail of a particular friend:

import {
  Component,
  Input,
  computed,
  signal
} from '@angular/core';
import {
  MyFriend,
  MyFriendsService
} from './my-friends.service';

@Component({
  selector: 'app-friend-detail',
  templateUrl: './friend-detail-component.html',
})
export class FriendDetailComponent {
  @Input() name = signal('Bob');
  friendDetail = computed < MyFriend > (() => {
    const friend = this.myFriendsService
      .myFriends()
      .filter((friend) => friend.name === this.name());
    if (friend.length > 0) {
      return friend[0];
    }
    return {
      name: '',
      age: 0,
    };
  });
  constructor(private myFriendsService: MyFriendsService) {}

The following component simply uses the FriendDetailComponent:

import {
  Component,
  signal
} from '@angular/core';

@Component({
  selector: 'app-some-component',
  template: `<app-friend-detail [name]="selectedName"></app-friend-detail>`,
})
export class SomeComponent {
  selectedName = signal < string > ('Julie');
}

As I said, this WORKS. But...is this a proper way to be using a signal in angular?

FYI, I realize that the FriendDetailComponent should be more "dumb" and just accept the input of the FriendDetail info (it need not use signals)...but I did this mock-up as a way to explain a pattern I fell into within the context of a more complex situation.

brando
  • 8,215
  • 8
  • 40
  • 59
  • 1
    You shouldn't be passing signals, just like you shouldn't pass Observables. If the child component is smart, give it access to the service. If it's dumb, then you should be passing it the already-consumed signal. As always, there's a lot of "it depends", but if signals are to be seen the same way as Observables, this will be an anti-pattern. – Will Alexander Jul 26 '23 at 21:15
  • Thanks @WillAlexander, you are expressing what my hunch is telling me. This is an anti-pattern. – brando Jul 26 '23 at 22:53

1 Answers1

2

Phase 2 (or maybe Phase 3) of Signals will introduce signal: true components, which will include two-way bindings.

The RFC https://github.com/angular/angular/discussions/49682 describes this under Model inputs.

In short (and API is subject to change) you will be able to define a special type of input that can be manipulated as a signal but will be a two way binding back to the parent.

But you won't be passing a signal directly, it will just appear as a signal inside the component.

If you're trying to pass signals to a component today you can do that via a service or just a normal input which is set to the evaluated signal value.

Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689