Skip to content

Commit

Permalink
docs(playground): 📘 add styling to signal mutation example
Browse files Browse the repository at this point in the history
  • Loading branch information
luii committed Nov 11, 2023
1 parent 6bb064a commit d9dd38b
Show file tree
Hide file tree
Showing 16 changed files with 238 additions and 59 deletions.
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@angular/router": "17.0.2",
"@ngneat/until-destroy": "^10.0.0",
"@nx/angular": "17.1.1",
"bulma": "^0.9.4",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "0.14.2"
Expand Down
2 changes: 1 addition & 1 deletion project.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"polyfills": ["zone.js"],
"tsConfig": "./tsconfig.app.json",
"assets": ["./src/favicon.ico", "./src/assets"],
"styles": ["./src/styles.scss"],
"styles": ["./src/styles.scss", "node_modules/bulma/css/bulma.min.css"],
"scripts": []
},
"configurations": {
Expand Down
42 changes: 35 additions & 7 deletions src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,36 @@
<a routerLink="basic">Basic</a>
<a routerLink="infinite-scroll">Infinite Scroll</a>
<a routerLink="pagination">Pagination</a>
<a routerLink="mutation">mutation</a>
<nav class="navbar is-white">
<div class="navbar-brand">
<a class="navbar-item" href="https://github.com/ngneat/query/">
<img src="./assets/ngneat.png" style="margin-right: 8px;">
<h1>&#64;ngneat/query Playground</h1>
</a>

<a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false" data-target="navbarBasicExample">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
</nav>

<div class="container">
<div class="columns is-5 is-variable">
<div class="column is-3">
<aside class="menu box">
<p class="menu-label">Examples</p>
<ul class="menu-list">
<li><a routerLinkActive="is-active-example" routerLink="basic">Basic</a></li>
<li><a routerLinkActive="is-active-example" routerLink="infinite-scroll">Infinite Scroll</a></li>
<li><a routerLinkActive="is-active-example" routerLink="pagination">Pagination</a></li>
<li><a routerLinkActive="is-active-example" routerLink="mutation">Mutation</a></li>
</ul>
</aside>
</div>
<main class="column is-9">
<div class="box">
<router-outlet></router-outlet>
</div>
</main>
</div>
</div>

<main>
<router-outlet></router-outlet>
</main>
107 changes: 60 additions & 47 deletions src/app/mutation-page/mutation-page.component.html
Original file line number Diff line number Diff line change
@@ -1,48 +1,61 @@
<div style="display: flex; flex-direction: column; gap: 8px; max-width: 720px; margin: auto">

<h1 style="text-align: center;">To see the mutation in action open the tanstack devtools and change to the mutation tab.</h1>

<h3 style="text-align: center;">Currently active Mutations: {{ addTodoMutationsActive() }}</h3>

<div style="display: flex; flex-direction: row; gap: 8px; ">
<fieldset style="flex: 1 0 auto; display: flex; flex-direction: column; gap: 8px;" id="signals">
<legend>Signals</legend>

<input id="signalTodo" placeholder="Input a new todo here..." [(ngModel)]="newTodo" style="margin-top: 16px;">
<button (click)="onAddTodo(newTodo)">Add Todo</button>
<button (click)="onAddTodoWithError(newTodo)">Add Todo with Error</button>
<button (click)="onResetMutation()">Reset Mutation</button>

<ng-container *ngIf="addTodoSignalResult() as addTodo">
<p *ngIf="addTodo.isPending">loading...</p>
<p *ngIf="addTodo.isIdle">Idling</p>
<div *ngIf="addTodo.isError">
<p>Could not add the Todo</p>
</div>
<p *ngIf="addTodo.isSuccess">
{{ addTodo.data.title }}
</p>
</ng-container>
</fieldset>

<fieldset style="flex: 1 0 auto; display: flex; flex-direction: column; gap: 8px;">
<legend>Observable</legend>

<input id="observableTodo" placeholder="Input a new todo here..." [(ngModel)]="newTodo" style="margin-top: 16px;">
<button (click)="onAddTodo(newTodo)">Add Todo</button>
<button (click)="onAddTodoWithError(newTodo)">Add Todo with Error</button>
<button (click)="onResetMutation()">Reset Mutation</button>

<ng-container *ngIf="addTodo.result$ | async as addTodo">
<p *ngIf="addTodo.isPending">loading...</p>
<p *ngIf="addTodo.isIdle">Idling</p>
<div *ngIf="addTodo.isError" style="word-break: break-all;">
<p>Could not add the Todo</p>
<div class="content">
<h1>Mutation Example</h1>

<p>This example shows how to use the Mutations API</p>
<p>To get a better understanding on what happens, open the <b>devtools</b> in the bottom right.</p>

<h4>Is Mutating: {{ addTodoMutationsActive() }}</h4>
</div>

<query-tabs>
<query-tab title="Signal API">
@if (addTodoSignalResult();as addTodo) {
<div class="block" style="margin: 4rem 0 2rem 0;">
<div class="field is-grouped is-horizontal">
<div class="control is-expanded">
<input class="input" placeholder="Todo title" id="signalTodo" type="text" [(ngModel)]="newTodo">
</div>
<div class="control">
<button
class="button is-primary-button"
(click)="onAddTodo(newTodo)"
[class.is-loading]="addTodo.isPending"
[disabled]="addTodo.isPending"
>
Add Todo
</button>
</div>
<div class="control">
<button class="button is-danger" (click)="onAddTodoWithError(newTodo)">Show Error</button>
</div>
<div class="control">
<button class="button is-black" (click)="onResetMutation()">Reset Mutation</button>
</div>
</div>
<p *ngIf="addTodo.isSuccess">
{{ addTodo.data.title }}
</p>
</ng-container>
</fieldset>
</div>
</div>
</div>
<div class="block content box">
<h4>Mutation Output</h4>
<code style="background-color: initial; max-height: 300px; overflow: hidden; overflow-y: auto; display: block">
<pre>{{ addTodo | json }}</pre>
</code>
</div>
}
</query-tab>
<query-tab title="Observable API">
<input id="observableTodo" placeholder="Input a new todo here..." [(ngModel)]="newTodo" style="margin-top: 16px;">
<button (click)="onAddTodo(newTodo)">Add Todo</button>
<button (click)="onAddTodoWithError(newTodo)">Add Todo with Error</button>
<button (click)="onResetMutation()">Reset Mutation</button>

@if (addTodo.result$ | async;as addTodo) {
<p *ngIf="addTodo.isPending">loading...</p>
<p *ngIf="addTodo.isIdle">Idling</p>
<div *ngIf="addTodo.isError" style="word-break: break-all;">
<p>Could not add the Todo</p>
</div>
<p *ngIf="addTodo.isSuccess">
{{ addTodo.data.title }}
</p>
}
</query-tab>
</query-tabs>
4 changes: 3 additions & 1 deletion src/app/mutation-page/mutation-page.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import { injectIsMutating } from '@ngneat/query';

import { FormsModule } from '@angular/forms';
import { TodosService } from '../services/todos.service';
import { TabsComponent } from '../ui/query-tabs/tabs.component';
import { TabComponent } from '../ui/query-tab/tab.component';
@Component({
selector: 'query-mutation-page',
standalone: true,
imports: [CommonModule, FormsModule],
imports: [CommonModule, FormsModule, TabsComponent, TabComponent],
templateUrl: './mutation-page.component.html',
styles: [],
changeDetection: ChangeDetectionStrategy.OnPush,
Expand Down
5 changes: 4 additions & 1 deletion src/app/services/todos.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { HttpClient } from '@angular/common/http';
import { Injectable, inject } from '@angular/core';
import { injectMutation, injectQuery, toPromise } from '@ngneat/query';
import { injectMutation, injectQuery, injectQueryClient, toPromise } from '@ngneat/query';

interface Todo {
id: number;
Expand All @@ -9,6 +9,7 @@ interface Todo {

@Injectable({ providedIn: 'root' })
export class TodosService {
#client = injectQueryClient();
#query = injectQuery();
#useMutation = injectMutation();
#http = inject(HttpClient);
Expand Down Expand Up @@ -41,6 +42,8 @@ export class TodosService {

addTodo() {
return this.#useMutation({
onSuccess: () => this.#client.invalidateQueries({queryKey: ['todos']}),
onError: (error) => console.log('This error was logged upon from the onError callback: ', error),
mutationFn: ({
title,
showError,
Expand Down
3 changes: 3 additions & 0 deletions src/app/ui/query-tab/tab.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div [class.is-hidden]="!active">
<ng-content />
</div>
21 changes: 21 additions & 0 deletions src/app/ui/query-tab/tab.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TabComponent } from './tab.component';

describe('TabComponent', () => {
let component: TabComponent;
let fixture: ComponentFixture<TabComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [TabComponent],
}).compileComponents();

fixture = TestBed.createComponent(TabComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
13 changes: 13 additions & 0 deletions src/app/ui/query-tab/tab.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Component, Input } from '@angular/core';

@Component({
selector: 'query-tab',
standalone: true,
imports: [],
templateUrl: './tab.component.html',
styles: '',
})
export class TabComponent {
@Input({ required: true }) title = '';
public active: boolean = false;
}
10 changes: 10 additions & 0 deletions src/app/ui/query-tabs/tabs.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<div class="tabs">
@if (tabs) {
<ul>
@for (tab of tabs.toArray(); track 'title'; let idx = $index) {
<li (click)="selectTab(tab)" [class.is-active-tab]="tab.active"><a>{{ tab.title }}</a></li>
}
</ul>
}
</div>
<ng-content />
21 changes: 21 additions & 0 deletions src/app/ui/query-tabs/tabs.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TabsComponent } from './tabs.component';

describe('TabsComponent', () => {
let component: TabsComponent;
let fixture: ComponentFixture<TabsComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [TabsComponent],
}).compileComponents();

fixture = TestBed.createComponent(TabsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
35 changes: 35 additions & 0 deletions src/app/ui/query-tabs/tabs.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {
AfterContentInit,
Component,
ContentChildren,
QueryList,
} from '@angular/core';
import { NgComponentOutlet, NgForOf } from '@angular/common';
import { TabComponent } from '../query-tab/tab.component';

@Component({
selector: 'query-tabs',
standalone: true,
imports: [NgForOf, NgComponentOutlet],
templateUrl: './tabs.component.html',
styles: `
.is-active-tab a {
color: #b93eff;
border-bottom-color: #b93eff;
}
`,
})
export class TabsComponent implements AfterContentInit {
@ContentChildren(TabComponent, { read: TabComponent })
tabs!: QueryList<TabComponent>;

ngAfterContentInit() {
const activeTabs = this.tabs.filter((tab) => tab.active);
if (activeTabs.length === 0) this.selectTab(this.tabs.first);
}

selectTab(tab: TabComponent) {
this.tabs.toArray().forEach((tab) => (tab.active = false));
tab.active = true;
}
}
Binary file added src/assets/ngneat.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/index.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<html lang="en" style="height: 100%;">
<head>
<meta charset="utf-8" />
<title>query</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
</head>
<body>
<body style="height: 100%;" class="is-light">
<query-root></query-root>
</body>
</html>
23 changes: 23 additions & 0 deletions src/styles.scss
Original file line number Diff line number Diff line change
@@ -1 +1,24 @@
/* You can add global styles to this file, and also import other style files */

body {
background-color: #F2F6FA;
}

.container .columns {
margin: 3rem 0;
}

.is-active-example {
background-color: #b93eff !important;
color: #fff !important;
}

.is-active-example:hover {
background-color: #AE08E4 !important;
color: #fff !important;
}

.is-primary-button {
background-color: #AE08E4 !important;
color: #fff !important;
}

0 comments on commit d9dd38b

Please sign in to comment.