Skip to content
This repository was archived by the owner on Mar 10, 2025. It is now read-only.
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
71 changes: 71 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,77 @@ export class MyComp extends Vue {
}
```

### Curried Getters

You might have a getter that returns a curried function in order to pass in parameters to your getter. E.g.:

```ts
const store = {
state: {
values: [
{ id: 1, value: "value 1" },
{ id: 2, value: "value 2" }
]
},
getters: {
byId: state => id => state.values.filter(v => v.id === id)[0].value
}
}

```

You could bind this getter to a function on your component class:

```ts
import Vue from 'vue'
import Component from 'vue-class-component'
import {
Getter
} from 'vuex-class'


@Component
export class MyComp extends Vue {

@Getter("byId") byId: (id: number) => string;
}
```

But you might have a static value that you want to bind to. In which case you can pass this to the args property of the binding options object:

```ts
import Vue from 'vue'
import Component from 'vue-class-component'
import {
Getter
} from 'vuex-class'


@Component
export class MyComp extends Vue {

@Getter("byId", { args: [1] }) value: string;
}
```

You might want to encapsulate this into your own decorator so you can strongly type the arguments:

```ts
import Vue from 'vue'
import Component from 'vue-class-component'
import {
Getter
} from 'vuex-class'

const ByIdGetter = (id: number) => @Getter("byId", { args: [id] })

@Component
export class MyComp extends Vue {

@ByIdGetter(1) byId: (id: number) => string;
}
```

## Issue Reporting Guideline

### Questions
Expand Down
41 changes: 30 additions & 11 deletions package-lock.json

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

60 changes: 53 additions & 7 deletions src/bindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import {
mapState,
mapGetters,
mapActions,
mapMutations
mapMutations,
Dictionary
} from 'vuex'

export type VuexDecorator = <V extends Vue> (proto: V, key: string) => void
Expand All @@ -15,7 +16,8 @@ export type MapHelper = typeof mapState | typeof mapGetters
| typeof mapActions | typeof mapMutations

export interface BindingOptions {
namespace?: string
namespace?: string,
args?: any[]
}

export interface BindingHelper {
Expand All @@ -36,7 +38,35 @@ export interface BindingHelpers {

export const State = createBindingHelper('computed', mapState) as StateBindingHelper

export const Getter = createBindingHelper('computed', mapGetters)

const curriedMapGetters = <R>(args: any[]) => {

function map(map: string[]): Dictionary<R>
function map(map: Dictionary<string>): Dictionary<R>
function map(namespace: string, map: string[]): Dictionary<R>
function map(namespace: string, map: Dictionary<string>): Dictionary<R>
function map(...mapArgs: any[]): Dictionary<R> {


const mappedGetters = (mapGetters as any)(...mapArgs)


const entries: ([string, any])[] = Object.keys(mappedGetters).map<[string, any]>(k => ([k, mappedGetters[k]]))

return entries.reduce(
(acc, [getter, fn]) => ({
...acc,
[getter]: (state: any) =>
fn.call(state)(...(Array.isArray(args) ? args : [args]))
}),
{}
)
}

return map
}

export const Getter = createBindingHelper('computed', mapGetters, curriedMapGetters)

export const Action = createBindingHelper('methods', mapActions)

Expand Down Expand Up @@ -77,24 +107,29 @@ export function namespace <T extends BindingHelper> (

return {
State: createNamespacedHelper(State as any),
Getter: createNamespacedHelper(Getter as any),
Getter: createNamespacedHelper(createBindingHelper('computed', mapGetters, curriedMapGetters) as any),
Mutation: createNamespacedHelper(Mutation as any),
Action: createNamespacedHelper(Action as any)
}
}

function createBindingHelper (
bindTo: 'computed' | 'methods',
mapFn: MapHelper
mapFn: MapHelper,
curriedMapFn?: (...args: any[]) => MapHelper
): BindingHelper {
function makeDecorator (map: any, namespace: string | undefined) {
function makeDecorator (map: any, namespace: string | undefined, args: any[] = []) {
return createDecorator((componentOptions, key) => {
if (!componentOptions[bindTo]) {
componentOptions[bindTo] = {}
}

const mapObject = { [key]: map }

if (args.length > 0 && curriedMapFn) {
mapFn = curriedMapFn(args)
}

componentOptions[bindTo]![key] = namespace !== undefined
? mapFn(namespace, mapObject)[key]
: mapFn(mapObject)[key]
Expand All @@ -111,8 +146,9 @@ function createBindingHelper (
}

const namespace = extractNamespace(b)
const args = extractArgs(b)
const type = a
return makeDecorator(type, namespace)
return makeDecorator(type, namespace, args)
}

return helper
Expand All @@ -132,6 +168,16 @@ function extractNamespace (options: BindingOptions | undefined): string | undefi
return n
}

function extractArgs(options: BindingOptions | undefined): any[] {
const args = options && options.args

if (args != null) {
return args
}

return []
}

function merge <T, U> (a: T, b: U): T & U {
const res: any = {}
;[a, b].forEach((obj: any) => {
Expand Down
Loading