diff --git a/packages/overmind-website/examples/guide/managinglists/render2.ts b/packages/overmind-website/examples/guide/managinglists/render2.ts index 12577b6b..b77e0199 100644 --- a/packages/overmind-website/examples/guide/managinglists/render2.ts +++ b/packages/overmind-website/examples/guide/managinglists/render2.ts @@ -57,7 +57,7 @@ export default connect({ target: 'markup', code: ` `, }, @@ -65,11 +65,11 @@ export default connect({ fileName: 'components/Posts.vue (script)', code: ` import { connect } from '../overmind' -import Post from './Post' +import PostComponent from './Post' export default connect({ components: { - Post, + PostComponent, }, }) `, diff --git a/packages/overmind-website/examples/guide/usingovermindwithangular/connect.ts b/packages/overmind-website/examples/guide/usingovermindwithangular/connect.ts new file mode 100644 index 00000000..ccf3fd81 --- /dev/null +++ b/packages/overmind-website/examples/guide/usingovermindwithangular/connect.ts @@ -0,0 +1,44 @@ +export default () => [ + { + fileName: 'overmind/index.ts', + code: ` +import { Overmind, TConfig } from 'overmind' +import { createConnect, TConnect } from 'overmind-angular' +import { state } from './state' +import * as actions from './actions' + +const config = { + state, + actions +} + +declare module 'overmind' { + interface IConfig extends TConfig {} +} + +export type Connect = TConnect + +const overmind = new Overmind(config) + +export const connect = createConnect(overmind) +`, + }, + { + fileName: 'components/app.component.ts', + code: ` +import { Component } from '@angular/core' +import { connect, Connect } from '../overmind' + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.css'] +}) +@connect() +export class AppComponent { + overmind: Connect + title = 'My First Angular App with Overmind!' +} +`, + }, +] diff --git a/packages/overmind-website/examples/guide/usingovermindwithangular/effect.ts b/packages/overmind-website/examples/guide/usingovermindwithangular/effect.ts new file mode 100644 index 00000000..4401a403 --- /dev/null +++ b/packages/overmind-website/examples/guide/usingovermindwithangular/effect.ts @@ -0,0 +1,29 @@ +export default () => [ + { + fileName: 'components/app.component.ts', + code: ` +import { Component } from '@angular/core' +import { connect, Connect } from '../overmind' + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html' +}) +@connect() +export class AppComponent { + overmind: Connect + disposeMutationListener: () => void + ngOnInit() { + this.disposeMutationListener = this.overmind.addMutationListener((mutation) => { + if (mutation.path === 'currentPage') { + document.querySelector('#app').scrollTop = 0 + } + }) + } + ngOnDestroy() { + this.disposeMutationListener() + } +} +`, + }, +] diff --git a/packages/overmind-website/examples/guide/usingovermindwithangular/onpush.ts b/packages/overmind-website/examples/guide/usingovermindwithangular/onpush.ts new file mode 100644 index 00000000..7f3cade1 --- /dev/null +++ b/packages/overmind-website/examples/guide/usingovermindwithangular/onpush.ts @@ -0,0 +1,25 @@ +export default () => [ + { + fileName: 'components/app.component.ts', + code: ` +import { + Component, + ChangeDetectionStrategy, + ChangeDetectorRef +} from '@angular/core' +import { connect, Connect } from '../overmind' + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.css'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +@connect() +export class AppComponent { + overmind: Connect + constructor(private cdr: ChangeDetectorRef) {} +} +`, + }, +] diff --git a/packages/overmind-website/examples/guide/usingovermindwithangular/passprop.ts b/packages/overmind-website/examples/guide/usingovermindwithangular/passprop.ts new file mode 100644 index 00000000..4f5bc4a3 --- /dev/null +++ b/packages/overmind-website/examples/guide/usingovermindwithangular/passprop.ts @@ -0,0 +1,42 @@ +export default () => [ + { + fileName: 'components/todo.component.ts', + code: ` +import { Component, Input } from '@angular/core' +import { connect } from '../overmind' +import { Todo } from '../overmind/state' + +@Component({ + selector: 'todos-todo', + template: \` +
  • {{todo.title}}
  • + \` +}) +@connect() +export class TodoComponent { + @Input() todo: Todo +} + `, + }, + { + fileName: 'components/todos.component.ts', + code: ` +import { Component } from '@angular/core' +import { connect } from '../overmind' + +@Component({ + selector: 'todos-list', + template: \` + + \` +}) +@connect() +export class ListComponent {} +`, + }, +] diff --git a/packages/overmind-website/examples/guide/usingovermindwithvue/connect.ts b/packages/overmind-website/examples/guide/usingovermindwithvue/connect.ts new file mode 100644 index 00000000..af457e04 --- /dev/null +++ b/packages/overmind-website/examples/guide/usingovermindwithvue/connect.ts @@ -0,0 +1,32 @@ +export default () => [ + { + fileName: 'overmind/index.jsx', + code: ` +import { Overmind } from 'overmind' +import { createConnect } from 'overmind-vue' + +const overmind = new Overmind({ + state: {}, + actions: {} +}) + +export const connect = createConnect(overmind) +`, + }, + { + fileName: 'components/SomeComponent.vue (template)', + code: ` +
    + {{overmind.state.foo}} +
    +`, + }, + { + fileName: 'components/SomeComponent.vue (script)', + code: ` +import { connect } from '../overmind' + +export default connect({}) +`, + }, +] diff --git a/packages/overmind-website/examples/guide/usingovermindwithvue/effect.ts b/packages/overmind-website/examples/guide/usingovermindwithvue/effect.ts new file mode 100644 index 00000000..a2b16495 --- /dev/null +++ b/packages/overmind-website/examples/guide/usingovermindwithvue/effect.ts @@ -0,0 +1,29 @@ +export default () => [ + { + fileName: 'components/SomeComponent.vue (template)', + code: ` +
    + {{overmind.state.foo}} +
    +`, + }, + { + fileName: 'components/SomeComponent.vue (script)', + code: ` +import { connect } from '../overmind' + +export default connect({ + mounted() { + this.disposeMutationListener = this.overmind.addMutationListener((mutation) => { + if (mutation.path === 'currentPage') { + document.querySelector('#app').scrollTop = 0 + } + }) + }, + destroyed() { + this.disposeMutationListener() + } +}) +`, + }, +] diff --git a/packages/overmind-website/examples/guide/usingovermindwithvue/passprops.ts b/packages/overmind-website/examples/guide/usingovermindwithvue/passprops.ts new file mode 100644 index 00000000..4b21ed8f --- /dev/null +++ b/packages/overmind-website/examples/guide/usingovermindwithvue/passprops.ts @@ -0,0 +1,57 @@ +export default () => [ + { + fileName: 'overmind/index.jsx', + code: ` +import { Overmind } from 'overmind' +import { createConnect } from 'overmind-vue' + +const overmind = new Overmind({ + state: {}, + actions: {} +}) + +export const connect = createConnect(overmind) +`, + }, + { + fileName: 'components/Todo.vue (template)', + code: ` +
  • {{todo.title}}
  • +`, + }, + { + fileName: 'components/Todo.vue (script)', + code: ` +import { connect } from '../overmind' + +export default connect({ + props: ["todo"] +}) +`, + }, + { + fileName: 'components/Todos.vue (template)', + code: ` + +`, + }, + { + fileName: 'components/Todos.vue (script)', + code: ` +import { connect } from '../overmind' +import TodoComponent from './Todo' + +export default connect({ + components: { + TodoComponent + } +}) +`, + }, +] diff --git a/packages/overmind-website/guides/beginner/06_usingovermindwithreact.md b/packages/overmind-website/guides/beginner/06_usingovermindwithreact.md index 363166ef..d7defe7e 100644 --- a/packages/overmind-website/guides/beginner/06_usingovermindwithreact.md +++ b/packages/overmind-website/guides/beginner/06_usingovermindwithreact.md @@ -23,7 +23,7 @@ If you previously used **componentDidUpdate** to trigger an effect, that is no l ### Passing state as props -If you pass a state object or array as a property to a child component you will also in the child component need to **connect**. This ensures that the property you passed is tracked within that component, even though you do not access any state or actions. The devtools will help you identify where any components are left "unconnected". +If you pass a state object or array as a property to a child component you will also in the child component need to **connect**. This ensures that the property you passed is tracked within that component, even though you do not access any state or actions from Overmind. The devtools will help you identify where any components are left "unconnected". ```marksy h(Example, { name: "guide/usingovermindwithreact/hoc_passprop" }) diff --git a/packages/overmind-website/guides/beginner/07_usingovermindwithangular.md b/packages/overmind-website/guides/beginner/07_usingovermindwithangular.md new file mode 100644 index 00000000..ee0e95bc --- /dev/null +++ b/packages/overmind-website/guides/beginner/07_usingovermindwithangular.md @@ -0,0 +1,36 @@ +# Using Overmind with Angular + +Using Overmind with Angular is straight forward. You create a **connect** decorator and use it with whatever component. An **overmind** property is added to the component and there you can access state, actions and listen to mutations to do effects. + +```marksy +h(Example, { name: "guide/usingovermindwithangular/connect" }) +``` + + +## Rendering + +When you connect Overmind to a component it will use its lifecycle hooks to manage updates. By default you really do not have to think about this as it relies on Angulars default change detection strategy.You can change this behaviour though. By adding the **onPush** strategy and injecting the **ChangeDetectorRef**, the component will only update when it receives input from its parents or Overmind tells it to update due to tracked state has changed. + +```marksy +h(Example, { name: "guide/usingovermindwithangular/onpush" }) +``` + +```marksy +h(Notice, null, "The class property has to be named **cdr**. Overmind gives an error if you use onPush strategy without injecting ChangeDetectorRef correctly.") +``` + +## Passing state as input + +If you pass a state object or array as a property to a child component you will also in the child component need to **connect**. This ensures that the property you passed is tracked within that component, even though you do not access any state or actions from Overmind. The devtools will help you identify where any components are left "unconnected". + +```marksy +h(Example, { name: "guide/usingovermindwithangular/passprop" }) +``` + +## Effects + +To run effects in components based on changes to state you use the **addMutationListener** function in the lifecycle hooks of Angular. + +```marksy +h(Example, { name: "guide/usingovermindwithangular/effect" }) +``` \ No newline at end of file diff --git a/packages/overmind-website/guides/beginner/08_usingovermindwithvue.md b/packages/overmind-website/guides/beginner/08_usingovermindwithvue.md new file mode 100644 index 00000000..46dc937a --- /dev/null +++ b/packages/overmind-website/guides/beginner/08_usingovermindwithvue.md @@ -0,0 +1,26 @@ +# Using Overmind with Vue + +You can connect any Vue component to your Overmind instance. + +```marksy +h(Example, { name: "guide/usingovermindwithvue/connect" }) +``` + +## Rendering +Any state accessed in the component will cause the component to render when a mutation occurs on that state. Overmind actually uses the same approach to change detection as Vue itself. + +## Pass state as props + +If you pass a state object or array as a property to a child component you will also in the child component need to **connect**. This ensures that the property you passed is tracked within that component, even though you do not access any state or actions from Overmind. The devtools will help you identify where any components are left "unconnected". + +```marksy +h(Example, { name: "guide/usingovermindwithvue/passprops" }) +``` + +## Effects + +To run effects in components based on changes to state you use the **addMutationListener** function in the lifecycle hooks of Vue. + +```marksy +h(Example, { name: "guide/usingovermindwithvue/effect" }) +``` \ No newline at end of file diff --git a/packages/overmind-website/guides/intermediate/02_routing.md b/packages/overmind-website/guides/intermediate/02_routing.md index 3fc8c556..cabee93b 100644 --- a/packages/overmind-website/guides/intermediate/02_routing.md +++ b/packages/overmind-website/guides/intermediate/02_routing.md @@ -1,4 +1,4 @@ -# Routing +# State first routing With Overmind you can use whatever routing solution your selected view layer provides. This will most likely intertwine routing state with your component state, which is something Overmind would discourage, but you know... whatever you feel productive in, you should use :-) In this guide we will look into how you can separate your router from your components and make it part of your application state instead. This is more in the spirit of Overmind and throughout this guide you will find benefits of doing it this way.