UNPKG

kea-react

Version:

Componentes comunes de react

108 lines (96 loc) 4.83 kB
import React = require('react'); import update = require('immutability-helper'); import interfaces = require("./interfaces"); /** * Llama al metodo onModelChanged con el nuevo objeto del modelo con los datos cambiados, * considerando que el modelo original es immutable */ export function handleModelPropertyChanged<TIn, TOut>(newValue: any, key: string, props: interfaces.ControlledValueProps<TIn, TOut>) { console.warn("use handleFormChange ya que esta tipado"); if (props.onChange) { var updateSpec = {}; updateSpec[key] = { $set: newValue }; var newModel : any = (update as any)(props.value!, updateSpec); props.onChange(newModel); } } /**Llama al método props.onChange incluyendo un cambio en una propiedad de value * @param change Objeto parcial que indica las propiedades que cambiaron de value, junto con sus nuevos valores * @param props Propiedades del componente */ export function handleChange<TIn, TOut>(change: Partial<TOut>, props: interfaces.ControlledValueProps<TIn, TOut>) { console.warn("use handleFormChange ya que esta tipado"); const newModel = Object.assign({}, props.value! || {}, change); if (props.onChange) props.onChange(newModel as any as TOut); } function createChangeFunction<TIn, TOut>(propsThunk: () => { value?: TIn, onChange?: (value: TOut) => void | PromiseLike<void> }, key: string) : HandleChangeFunction<any> { const changeFunc = ((value) => ({ [key as string]: value } as Partial<TOut>)); return async function (value: any) { const props = propsThunk(); if (props.onChange) { const change = changeFunc(value); const newModel = Object.assign({}, props.value! || {}, change); await props.onChange(newModel as any as TOut); } } } export interface HandleChangeFunction<T> { (value: T): PromiseLike<void> } export interface HandleChangeNameFunction<T> { <K extends keyof T>(key : K) : HandleChangeFunction<T[K]>; } /** * Devuelve una curry-function que toma el props, el nombre de una propiedad de value, y el nuevo valor a asignar en esa propiedad. * La segunda funcion siempre devuelve la misma instancia para el mismo nombre de propiedad * En su clase cree la funcion de cambio: * const handleChange = handleFormChange(() => this.props); * * En los componentes editores: * <Text value={this.props.text} onChange={handleChange("Nombre")} /> * * @param propsThunk Funcion que devuelve un objeto con el valor actual y la función de cambio * @param key Nombre de la propiedad * @param value Nuevo valor de la propiedad. * */ export function handleFormChange<TIn, TOut>(propsThunk: () => { value?: TIn, onChange?: (value: TOut) => void | PromiseLike<void> }) : HandleChangeNameFunction<TOut> { type cacheType = { [P in keyof TOut]?: HandleChangeFunction<TOut[P]>; }; const cache: cacheType = {}; return function <K extends keyof TOut>(key: K) { return cache[key] || (cache[key] = createChangeFunction(propsThunk, key)) } } /**Devuelve una función que maneja el onChange de un control de una forma, donde la propiedad cambiada es una propiedad de props.value. * Siempre devuelve la misma instancia de la función para un changeFunction equivalente. * Esta es la manera recomendada de manejar el onChange en una forma ya que al devolver siempre la misma función para el mismo campo, evitamos redibujar el campo * * @param changeFunction Función que dado un nuevo valor devuelve un objecto parcial con la propiedad que se va a cambiar asignada al nuevo valor de esa propiedad. Esta función debe de ser pura * @param propsThunk Función que devuelve el value y el onChange de la forma * @param cache Objeto donde se va a almacenar el cache de funciones */ export function onChange<TIn, TOut>(changeFunction: (value: any) => Partial<TOut>, propsThunk: () => interfaces.ControlledValueProps<TIn, TOut>, cache: { [name: string]: any }) { console.warn("use handleFormChange ya que esta tipado"); const keys = Object.keys(changeFunction("test")); if (keys.length != 1) { throw "La función del handleChange debe de ser pura y devolver un objeto con solo una propiedad"; } const key = keys[0]; if (cache[key]) { return cache[key]; } else { const newFunc = newValue => { const props = propsThunk(); const change = changeFunction(newValue); const newModel = Object.assign({}, props.value! || {}, change); if (props.onChange) { props.onChange(newModel as any as TOut); } }; cache[key] = newFunc; return newFunc; } }