Skip to content

translate: translations for signals guide #19

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 8 additions & 18 deletions adev-es/src/app/sub-navigation-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [
],
},
{
label: 'In-depth Guides',
label: 'Guías Detalladas',
children: [
{
label: 'Componentes',
Expand Down Expand Up @@ -339,29 +339,19 @@ const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [
label: 'Signals',
children: [
{
label: 'Overview',
label: 'Visión general',
path: 'guide/signals',
contentPath: 'guide/signals/overview',
},
{
label: 'RxJS Interop',
path: 'guide/signals/rxjs-interop',
contentPath: 'guide/signals/rxjs-interop',
},
{
label: 'Inputs as signals',
path: 'guide/signals/inputs',
contentPath: 'guide/signals/inputs',
},
{
label: 'Model inputs',
path: 'guide/signals/model',
contentPath: 'guide/signals/model',
label: 'Estado dependiente con linkedSignal',
path: 'guide/signals/linked-signal',
contentPath: 'guide/signals/linked-signal',
},
{
label: 'Queries as signals',
path: 'guide/signals/queries',
contentPath: 'guide/signals/queries',
label: 'Reactividad asíncrona con resource',
path: 'guide/signals/resource',
contentPath: 'guide/signals/resource',
},
],
},
Expand Down
147 changes: 0 additions & 147 deletions adev-es/src/content/guide/signals/inputs.md

This file was deleted.

131 changes: 131 additions & 0 deletions adev-es/src/content/guide/signals/linked-signal.en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Dependent state with `linkedSignal`

You can use the `signal` function to hold some state in your Angular code. Sometimes, this state depends on some _other_ state. For example, imagine a component that lets the user select a shipping method for an order:

```typescript
@Component({/* ... */})
export class ShippingMethodPicker {
shippingOptions: Signal<ShippingMethod[]> = getShippingOptions();

// Select the first shipping option by default.
selectedOption = signal(this.shippingOptions()[0]);

changeShipping(newOptionIndex: number) {
this.selectedOption.set(this.shippingOptions()[newOptionIndex]);
}
}
```

In this example, the `selectedOption` defaults to the first option, but changes if the user selects another option. But `shippingOptions` is a signal— its value may change! If `shippingOptions` changes, `selectedOption` may contain a value that is no longer a valid option.

**The `linkedSignal` function lets you create a signal to hold some state that is intrinsically _linked_ to some other state.** Revisiting the example above, `linkedSignal` can replace `signal`:

```typescript
@Component({/* ... */})
export class ShippingMethodPicker {
shippingOptions: Signal<ShippingMethod[]> = getShippingOptions();

// Initialize selectedOption to the first shipping option.
selectedOption = linkedSignal(() => this.shippingOptions()[0]);

changeShipping(index: number) {
this.selectedOption.set(this.shippingOptions()[index]);
}
}
```

`linkedSignal` works similarly to `signal` with one key difference— instead of passing a default value, you pass a _computation function_, just like `computed`. When the value of the computation changes, the value of the `linkedSignal` changes to the computation result. This helps ensure that the `linkedSignal` always has a valid value.

The following example shows how the value of a `linkedSignal` can change based on its linked state:

```typescript
const shippingOptions = signal(['Ground', 'Air', 'Sea']);
const selectedOption = linkedSignal(() => shippingOptions()[0]);
console.log(selectedOption()); // 'Ground'

selectedOption.set(shippingOptions()[2]);
console.log(selectedOption()); // 'Sea'

shippingOptions.set(['Email', 'Will Call', 'Postal service']);
console.log(selectedOption()); // 'Email'
```

## Accounting for previous state

In some cases, the computation for a `linkedSignal` needs to account for the previous value of the `linkedSignal`.

In the example above, `selectedOption` always updates back to the first option when `shippingOptions` changes. You may, however, want to preserve the user's selection if their selected option is still somewhere in the list. To accomplish this, you can create a `linkedSignal` with a separate _source_ and _computation_:

```typescript
interface ShippingMethod {
id: number;
name: string;
}

@Component({/* ... */})
export class ShippingMethodPicker {
constructor() {
this.changeShipping(2);
this.changeShippingOptions();
console.log(this.selectedOption()); // {"id":2,"name":"Postal Service"}
}

shippingOptions = signal<ShippingMethod[]>([
{ id: 0, name: 'Ground' },
{ id: 1, name: 'Air' },
{ id: 2, name: 'Sea' },
]);

selectedOption = linkedSignal<ShippingMethod[], ShippingMethod>({
// `selectedOption` is set to the `computation` result whenever this `source` changes.
source: this.shippingOptions,
computation: (newOptions, previous) => {
// If the newOptions contain the previously selected option, preserve that selection.
// Otherwise, default to the first option.
return (
newOptions.find((opt) => opt.id === previous?.value.id) ?? newOptions[0]
);
},
});

changeShipping(index: number) {
this.selectedOption.set(this.shippingOptions()[index]);
}

changeShippingOptions() {
this.shippingOptions.set([
{ id: 0, name: 'Email' },
{ id: 1, name: 'Sea' },
{ id: 2, name: 'Postal Service' },
]);
}
}
```

When you create a `linkedSignal`, you can pass an object with separate `source` and `computation` properties instead of providing just a computation.

The `source` can be any signal, such as a `computed` or component `input`. When the value of `source` changes, `linkedSignal` updates its value to the result of the provided `computation`.

The `computation` is a function that receives the new value of `source` and a `previous` object. The `previous` object has two properties— `previous.source` is the previous value of `source`, and `previous.value` is the previous result of the `computation`. You can use these previous values to decide the new result of the computation.

HELPFUL: When using the `previous` parameter, it is necessary to provide the generic type arguments of `linkedSignal` explicitly. The first generic type corresponds with the type of `source` and the second generic type determines the output type of `computation`.

## Custom equality comparison

`linkedSignal`, as any other signal, can be configured with a custom equality function. This function is used by downstream dependencies to determine if that value of the `linkedSignal` (result of a computation) changed:

```typescript
const activeUser = signal({id: 123, name: 'Morgan', isAdmin: true});

const activeUserEditCopy = linkedSignal(() => activeUser(), {
// Consider the user as the same if it's the same `id`.
equal: (a, b) => a.id === b.id,
});

// Or, if separating `source` and `computation`
const activeUserEditCopy = linkedSignal({
source: activeUser,
computation: user => user,
equal: (a, b) => a.id === b.id,
});
```
Loading
Loading