Skip to content

Commit 8897b49

Browse files
docs: add example for output and model (#443)
1 parent c079865 commit 8897b49

File tree

2 files changed

+72
-3
lines changed

2 files changed

+72
-3
lines changed

apps/example-app/src/app/examples/22-signal-inputs.component.spec.ts

+58
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,73 @@
11
import { render, screen } from '@testing-library/angular';
22
import { SignalInputComponent } from './22-signal-inputs.component';
3+
import userEvent from '@testing-library/user-event';
34

45
test('works with signal inputs', async () => {
56
await render(SignalInputComponent, {
67
componentInputs: {
8+
greeting: 'Hello',
79
name: 'world',
10+
},
11+
});
12+
13+
expect(screen.getByText(/hello world/i)).toBeInTheDocument();
14+
});
15+
16+
test('can update signal inputs', async () => {
17+
const { fixture } = await render(SignalInputComponent, {
18+
componentInputs: {
819
greeting: 'Hello',
20+
name: 'world',
921
},
1022
});
1123

1224
expect(screen.getByText(/hello world/i)).toBeInTheDocument();
25+
26+
fixture.componentInstance.name.set('updated');
27+
// set doesn't trigger change detection within the test, findBy is needed to update the template
28+
expect(await screen.findByText(/hello updated/i)).toBeInTheDocument();
29+
// it's not recommended to access the model directly, but it's possible
30+
expect(fixture.componentInstance.name()).toBe('updated');
31+
});
32+
33+
test('output emits a value', async () => {
34+
const submitFn = jest.fn();
35+
await render(SignalInputComponent, {
36+
componentInputs: {
37+
greeting: 'Hello',
38+
name: 'world',
39+
},
40+
componentOutputs: {
41+
submit: { emit: submitFn } as any,
42+
},
43+
});
44+
45+
await userEvent.click(screen.getByRole('button'));
46+
47+
expect(submitFn).toHaveBeenCalledWith('world');
48+
});
49+
50+
test('model update also updates the template', async () => {
51+
const { fixture } = await render(SignalInputComponent, {
52+
componentInputs: {
53+
greeting: 'Hello',
54+
name: 'initial',
55+
},
56+
});
57+
58+
expect(screen.getByText(/hello initial/i)).toBeInTheDocument();
59+
60+
await userEvent.clear(screen.getByRole('textbox'));
61+
await userEvent.type(screen.getByRole('textbox'), 'updated');
62+
63+
expect(screen.getByText(/hello updated/i)).toBeInTheDocument();
64+
expect(fixture.componentInstance.name()).toBe('updated');
65+
66+
fixture.componentInstance.name.set('new value');
67+
// set doesn't trigger change detection within the test, findBy is needed to update the template
68+
expect(await screen.findByText(/hello new value/i)).toBeInTheDocument();
69+
// it's not recommended to access the model directly, but it's possible
70+
expect(fixture.componentInstance.name()).toBe('new value');
1371
});
1472

1573
test('works with signal inputs and rerenders', async () => {
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
1-
import { Component, input } from '@angular/core';
1+
import { Component, input, model, output } from '@angular/core';
2+
import { FormsModule } from '@angular/forms';
23

34
@Component({
45
selector: 'app-signal-input',
5-
template: ` {{ greetings() }} {{ name() }} `,
6+
template: `
7+
<div>{{ greetings() }} {{ name() }}</div>
8+
<button (click)="submitName()">Submit</button>
9+
<input type="text" [(ngModel)]="name" />
10+
`,
611
standalone: true,
12+
imports: [FormsModule],
713
})
814
export class SignalInputComponent {
915
greetings = input<string>('', {
1016
alias: 'greeting',
1117
});
12-
name = input.required<string>();
18+
name = model.required<string>();
19+
submit = output<string>();
20+
21+
submitName() {
22+
this.submit.emit(this.name());
23+
}
1324
}

0 commit comments

Comments
 (0)