Skip to content

Commit

Permalink
feat(cdk:forms): add watchValue and watchStatus (#143)
Browse files Browse the repository at this point in the history
re #115
  • Loading branch information
danranVm authored Jan 17, 2021
1 parent 3ecb231 commit 0cdc3ac
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 6 deletions.
78 changes: 76 additions & 2 deletions packages/cdk/forms/__tests__/abstractControl.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { flushPromises } from '@vue/test-utils'
import { Ref, ref } from 'vue'
import { Ref, ref, watch } from 'vue'
import { AbstractControl } from '../src/controls/abstractControl'
import { AsyncValidatorFn, ValidationErrors, ValidatorFn, ValidatorOptions } from '../src/types'
import { Validators } from '../src/validators'
Expand All @@ -11,9 +11,12 @@ class Control<T = unknown> extends AbstractControl<T> {
asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[] | null,
) {
super(validatorOrOptions, asyncValidator)
this._watchEffect()
}
reset(): void {}
setValue(_: T | null): void {}
setValue(value: T | null): void {
this.valueRef.value = value
}
getValue(): T {
return this.valueRef.value as T
}
Expand All @@ -22,6 +25,16 @@ class Control<T = unknown> extends AbstractControl<T> {
async validate(): Promise<ValidationErrors | null> {
return this._validate()
}

private _watchEffect() {
watch([this.valueRef, this.blurred], () => {
this._validate()
})

watch(this.errors, errors => {
this._status.value = errors ? 'invalid' : 'valid'
})
}
}

describe('abstractControl.ts', () => {
Expand Down Expand Up @@ -118,6 +131,67 @@ describe('abstractControl.ts', () => {
parent.setParent(root as any)
expect(control.root).toEqual(root)
})

test('watchValue work', async () => {
const log = jest.fn()
const stop = control.watchValue(value => log(value))

control.setValue('test')
await flushPromises()

expect(log).toBeCalledWith('test')
expect(log).toBeCalledTimes(1)

control.setValue('')
await flushPromises()

expect(log).toBeCalledWith('')
expect(log).toBeCalledTimes(2)

stop()

control.setValue('test')
await flushPromises()

expect(log).toBeCalledTimes(2)

control.watchValue(value => log(value), { immediate: true })
await flushPromises()

expect(log).toBeCalledWith('test')
expect(log).toBeCalledTimes(3)
})

test('watchStatus work', async () => {
const log = jest.fn()
const stop = control.watchStatus(value => log(value))

control.setValidator(Validators.required)
control.setValue('')
await flushPromises()

expect(log).toBeCalledWith('invalid')
expect(log).toBeCalledTimes(1)

control.setValue('test')
await flushPromises()

expect(log).toBeCalledWith('valid')
expect(log).toBeCalledTimes(2)

stop()

control.setValue('')
await flushPromises()

expect(log).toBeCalledTimes(2)

control.watchValue(value => log(value), { immediate: true })
await flushPromises()

expect(log).toBeCalledWith('invalid')
expect(log).toBeCalledTimes(3)
})
})

describe('convert options work', () => {
Expand Down
29 changes: 25 additions & 4 deletions packages/cdk/forms/src/controls/abstractControl.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
/* eslint-disable @typescript-eslint/no-explicit-any */

import type { ComputedRef, DeepReadonly, Ref } from 'vue'
import type { ComputedRef, DeepReadonly, Ref, WatchCallback, WatchOptions, WatchStopHandle } from 'vue'
import type {
AsyncValidatorFn,
ErrorMessages,
Expand All @@ -15,7 +15,7 @@ import type {
import type { FormGroup } from './formGroup'
import type { FormArray } from './formArray'

import { computed, readonly, ref } from 'vue'
import { computed, watch, readonly, ref } from 'vue'
import { hasOwnProperty, isArray, isNil, isObject } from '@idux/cdk/utils'
import { Validators } from '../validators'
import { isFormArray, isFormGroup } from '../typeof'
Expand Down Expand Up @@ -209,7 +209,6 @@ export abstract class AbstractControl<T = any> {
}

/**
* @description
* Reports error data for the control with the given path.
*
* @param errorCode The code of the error to check
Expand All @@ -222,7 +221,6 @@ export abstract class AbstractControl<T = any> {
}

/**
* @description
* Reports whether the control with the given path has the error specified.
*
* @param errorCode The code of the error to check
Expand All @@ -241,6 +239,29 @@ export abstract class AbstractControl<T = any> {
this._parent = parent
}

/**
* Watch the ref value for the control.
*
* @param cb The callback when the value changes
* @param options Optional options of watch, the default value of `deep` is `true`
*/
watchValue(cb: WatchCallback<T, T | undefined>, options?: WatchOptions): WatchStopHandle {
return watch(this.valueRef, cb, { deep: true, ...options })
}

/**
* Watch the status for the control.
*
* @param cb The callback when the status changes
* @param options Optional options of watch
*/
watchStatus(
cb: WatchCallback<ValidationStatus, ValidationStatus | undefined>,
options?: WatchOptions,
): WatchStopHandle {
return watch(this.status, cb, options)
}

protected async _validate(): Promise<ValidationErrors | null> {
const value = this.getValue()
let newErrors = this._runValidator(value)
Expand Down

0 comments on commit 0cdc3ac

Please sign in to comment.