This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| export interface ProductSchema { | |
| title: string; | |
| description: string; | |
| price: number; | |
| } | |
| // define a validation schema | |
| export const productSchema = schema<ProductSchema>(ctx => { | |
| required(ctx.title); | |
| min(ctx.price, 0); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function notEmptyArray( | |
| path: FieldPath<unknown[]>, | |
| // define a condition for when to perform a check | |
| // by default, validate always | |
| options: {when: () => boolean} = {when: () => true}, | |
| ) { | |
| validate(path, (ctx) => { | |
| const value = ctx.value(); | |
| if (options.when() && value.length === 0) { | |
| return customError({ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function passwordsEqual(path: FieldPath<{ | |
| password: string; confirmPassword: string | |
| }>) { | |
| validate(path, (ctx) => { | |
| const value = ctx.value(); | |
| if (value.password !== value.confirmPassword) { | |
| return customError({ kind: 'notEqual', message: 'Passwords must match' }); | |
| } | |
| return null; | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function password(path: FieldPath<string>) { | |
| validate(path, (ctx) => { | |
| const value = ctx.value(); | |
| if (value && value.length < 8) { | |
| // you can return different errors for different cases using the "kind" field | |
| return customError({ | |
| kind: 'tooShort', message: 'Password must be at least 8 characters long', | |
| }); | |
| } | |
| if (value && !/[A-Z]/.test(value)) { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @Injectable({providedIn: 'root'}) | |
| export class PortalService { | |
| // we can have multiple portals | |
| portals = signal<Record<string, TemplateRef<any>>>({}); | |
| // get one of the templates to use in your component | |
| getPortal(portalName: string) { | |
| return computed(() => this.portals()[portalName]); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| export class TodoStore { | |
| readonly #todoService = inject(TodoService); | |
| query = signal(''); | |
| todosResource = httpResource(() => ({ | |
| url: '/api/todos', | |
| params: { q: this.query() }, | |
| method: 'get', | |
| }), | |
| // use a default value and parsing with Zod | |
| {defaultValue: [], parse: todoListSchema.parse}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @Component({ | |
| template: ` | |
| @if (todo.hasValue()) { | |
| <form (ngSubmit)="save()"> | |
| <input [(ngModel)]="todo.value().title" /> | |
| <button type="submit">Save</button> | |
| </form> | |
| } | |
| `, | |
| imports: [FormsModule], |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { Component, computed, effect, inject, signal } from '@angular/core'; | |
| import { HttpClient } from '@angular/common/http'; | |
| import { forkJoin } from 'rxjs'; | |
| import { toSignal } from '@angular/core/rxjs-interop'; | |
| @Component({ | |
| template: ` | |
| @if (loading()) { | |
| <div>Loading...</div> | |
| } @else { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @Component({ | |
| template: ` | |
| @if (todos.hasValue()) { | |
| <select [(ngModel)]="todoId"> | |
| @for (todo of todos.value(); track todo.id) { | |
| <option [value]="todo.id">{{ todo.title }}</option> | |
| } | |
| </select> | |
| } | |
| @if (todo.hasValue()) { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @Component({ | |
| template: ` | |
| @if (todos.hasValue()) { | |
| <select [(ngModel)]="todoId"> | |
| @for (todo of todos.value(); track todo.id) { | |
| <option [value]="todo.id">{{ todo.title }}</option> | |
| } | |
| </select> | |
| } | |
| @if (todo.hasValue()) { |
NewerOlder