Merge pull request #80 from houdiniproject/reactify_inputs
Making inputs more natural in React
This commit is contained in:
commit
1a779f48d4
12 changed files with 384 additions and 87 deletions
|
@ -5,15 +5,16 @@ import {Field} from "../../../../types/mobx-react-form";
|
|||
import LabeledFieldComponent from "./LabeledFieldComponent";
|
||||
import {injectIntl, InjectedIntl} from 'react-intl';
|
||||
import {HoudiniField} from "../../lib/houdini_form";
|
||||
import ReactInput from "./form/ReactInput";
|
||||
|
||||
|
||||
export const BasicField = injectIntl(observer((props:{field:Field, intl?:InjectedIntl, wrapperClassName?:string}) =>{
|
||||
export const BasicField = observer((props:{field:Field, placeholder?:string, label?:string, wrapperClassName?:string}) =>{
|
||||
let field = props.field as HoudiniField
|
||||
return <LabeledFieldComponent
|
||||
inputId={props.field.id} labelText={field.label} inError={field.hasError} error={field.error}
|
||||
inStickyError={field.hasServerError} stickyError={field.serverError}
|
||||
className={props.wrapperClassName} >
|
||||
|
||||
<input {...props.field.bind()} placeholder={field.placeholder ? props.intl.formatMessage({id:field.placeholder}) : undefined} className="form-control"/>
|
||||
<ReactInput field={field} label={props.label} placeholder={props.placeholder} className="form-control"/>
|
||||
</LabeledFieldComponent>
|
||||
}))
|
||||
})
|
49
javascripts/src/components/common/form/ReactForm.tsx
Normal file
49
javascripts/src/components/common/form/ReactForm.tsx
Normal file
|
@ -0,0 +1,49 @@
|
|||
// License: LGPL-3.0-or-later
|
||||
import * as React from 'react';
|
||||
import { observer, Provider } from 'mobx-react';
|
||||
import {Field, Form} from "mobx-react-form";
|
||||
import {observable, action, toJS} from 'mobx';
|
||||
|
||||
export interface ReactFormProps
|
||||
{
|
||||
form:Form
|
||||
}
|
||||
|
||||
///Mostly useless class but, at some point, will replace all our form elements
|
||||
@observer
|
||||
export class ReactForm extends React.Component<ReactFormProps, {}> {
|
||||
|
||||
|
||||
|
||||
@observable
|
||||
form:Form
|
||||
|
||||
@action.bound
|
||||
componentWillMount()
|
||||
{
|
||||
this.form = this.props.form
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
componentDidUpdate(){
|
||||
|
||||
|
||||
}
|
||||
|
||||
componentWillUnmount(){
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
|
||||
return <form >
|
||||
{this.props.children}
|
||||
</form>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
164
javascripts/src/components/common/form/ReactInput.spec.tsx
Normal file
164
javascripts/src/components/common/form/ReactInput.spec.tsx
Normal file
|
@ -0,0 +1,164 @@
|
|||
// License: LGPL-3.0-or-later
|
||||
import * as React from 'react';
|
||||
import 'jest';
|
||||
import ReactInput from './ReactInput'
|
||||
import {Form} from "mobx-react-form";
|
||||
import {mount} from 'enzyme';
|
||||
import {toJS, observable, action, runInAction} from 'mobx';
|
||||
import {observer} from 'mobx-react';
|
||||
import {InputHTMLAttributes} from 'react';
|
||||
import {ReactForm} from "./ReactForm";
|
||||
|
||||
|
||||
|
||||
@observer
|
||||
class TestChange extends React.Component{
|
||||
@observable
|
||||
remove:boolean
|
||||
@observable
|
||||
form: Form
|
||||
|
||||
@action.bound
|
||||
componentWillMount(){
|
||||
this.form = new Form({fields:[{
|
||||
name: 'name',
|
||||
extra: null}
|
||||
]})
|
||||
}
|
||||
|
||||
|
||||
|
||||
@action.bound
|
||||
onClick(){
|
||||
this.remove = true
|
||||
}
|
||||
render() {
|
||||
let reactInput = !this.remove ? <ReactInput field={this.form.$('name')} label={'label1'} placeholder={"holder"}>
|
||||
{this.props.children}
|
||||
</ReactInput> : undefined
|
||||
|
||||
return <ReactForm form={this.form}>
|
||||
|
||||
{reactInput}
|
||||
<button onClick={() => this.onClick()}/>
|
||||
</ReactForm>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class WrappedInput extends React.Component<InputHTMLAttributes<HTMLInputElement>>{
|
||||
|
||||
render(){
|
||||
let notChildren = {...this.props}
|
||||
delete notChildren.children
|
||||
return <div>
|
||||
<input {...notChildren} />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
describe('ReactInput', () => {
|
||||
|
||||
let form: Form
|
||||
beforeEach(() => {
|
||||
form = new Form({
|
||||
fields: [
|
||||
{
|
||||
name: 'name',
|
||||
extra: null
|
||||
}
|
||||
]
|
||||
})
|
||||
})
|
||||
|
||||
describe('no children passed in', () => {
|
||||
test('gets added properly', () => {
|
||||
let res = mount(<ReactForm form={form}>
|
||||
<ReactInput field={form.$('name')} label={"label"}
|
||||
placeholder={"holder"} value={'snapshot'} aria-required={true}/>
|
||||
|
||||
</ReactForm>)
|
||||
|
||||
|
||||
//Did the attributes settings work as expected back to the objects
|
||||
expect(form.$('name').label).toEqual('label')
|
||||
expect(form.$('name').placeholder).toEqual('holder')
|
||||
expect(form.$('name').value).toEqual('')
|
||||
|
||||
//is the aria attribute passted through to the input
|
||||
let input = res.find('input')
|
||||
expect(input.prop('aria-required')).toEqual(true)
|
||||
|
||||
|
||||
// is the input properly bound?
|
||||
input.simulate('change', {target: { value: 'something' } })
|
||||
expect(form.$('name').value).toEqual('something')
|
||||
})
|
||||
|
||||
test('gets removed properly', () => {
|
||||
|
||||
let res = mount(<TestChange/>)
|
||||
|
||||
// The two casts are needed because Typescript was going blowing up without the 'any' first.
|
||||
// Why was it? *shrugs*
|
||||
let f = res.find('ReactForm').instance() as any as ReactForm
|
||||
expect(f.form.size).toEqual(1)
|
||||
|
||||
res.find('input').simulate('change', {target: { value: 'something' } })
|
||||
|
||||
expect(f.form.$('name').value).toEqual('something')
|
||||
|
||||
res.find('button').simulate('click')
|
||||
expect(f.form.size).toEqual(1)
|
||||
|
||||
expect(toJS(res.find('form'))).toMatchSnapshot()
|
||||
|
||||
expect(f.form.$('name').label).toEqual('label1')
|
||||
expect(f.form.$('name').placeholder).toEqual('holder')
|
||||
})
|
||||
})
|
||||
|
||||
describe('children passed in', () => {
|
||||
test('gets added properly', () => {
|
||||
let res = mount(<ReactForm form={form}>
|
||||
<ReactInput field={form.$('name')} label={"label"}
|
||||
placeholder={"holder"} value={'snapshot'} aria-required={true}>
|
||||
<WrappedInput/>
|
||||
</ReactInput>
|
||||
|
||||
</ReactForm>)
|
||||
|
||||
//Did the attributes settings work as expected back to the objects
|
||||
expect(form.$('name').label).toEqual('label')
|
||||
expect(form.$('name').placeholder).toEqual('holder')
|
||||
expect(form.$('name').value).toEqual('')
|
||||
|
||||
//is the aria attribute passted through to the input
|
||||
let input = res.find('input')
|
||||
expect(input.prop('aria-required')).toEqual(true)
|
||||
|
||||
|
||||
// is the input properly bound?
|
||||
input.simulate('change', {target: { value: 'something' } })
|
||||
expect(form.$('name').value).toEqual('something')
|
||||
})
|
||||
|
||||
test('gets removed properly', () => {
|
||||
|
||||
let res = mount(<TestChange>
|
||||
<WrappedInput/>
|
||||
</TestChange>)
|
||||
let f = res.find('ReactForm').instance() as any as ReactForm
|
||||
res.find('input').simulate('change', {target: { value: 'something' } })
|
||||
|
||||
expect(f.form.$('name').value).toEqual('something')
|
||||
expect(f.form.size).toEqual(1)
|
||||
res.find('button').simulate('click')
|
||||
expect(f.form.size).toEqual(1)
|
||||
|
||||
expect(f.form.$('name').label).toEqual('label1')
|
||||
expect(f.form.$('name').placeholder).toEqual('holder')
|
||||
})
|
||||
|
||||
})
|
||||
})
|
90
javascripts/src/components/common/form/ReactInput.tsx
Normal file
90
javascripts/src/components/common/form/ReactInput.tsx
Normal file
|
@ -0,0 +1,90 @@
|
|||
// License: LGPL-3.0-or-later
|
||||
import * as React from 'react';
|
||||
import { observer, inject, Provider } from 'mobx-react';
|
||||
import {InjectedIntlProps, injectIntl} from 'react-intl';
|
||||
import {Field} from "mobx-react-form";
|
||||
import {observable, action, toJS, runInAction} from 'mobx';
|
||||
import {InputHTMLAttributes} from 'react';
|
||||
|
||||
|
||||
|
||||
export interface ReactInputProps
|
||||
{
|
||||
field:Field
|
||||
label?:string
|
||||
placeholder?:string
|
||||
}
|
||||
|
||||
function castToNullIfUndef(i:any){
|
||||
return i === undefined ? null : i
|
||||
}
|
||||
|
||||
|
||||
class ReactInput extends React.Component<ReactInputProps & InputHTMLAttributes<HTMLInputElement>, {}> {
|
||||
|
||||
constructor(props:ReactInputProps){
|
||||
super(props)
|
||||
}
|
||||
|
||||
@observable
|
||||
field:Field
|
||||
|
||||
|
||||
@action.bound
|
||||
componentWillMount(){
|
||||
|
||||
this.field = this.props.field
|
||||
|
||||
|
||||
this.updateProps()
|
||||
}
|
||||
|
||||
componentWillUnmount(){
|
||||
}
|
||||
|
||||
|
||||
componentDidUpdate(prevProps: Readonly<ReactInputProps>, prevState: Readonly<{}>): void {
|
||||
this.updateProps()
|
||||
}
|
||||
|
||||
@action.bound
|
||||
updateProps() {
|
||||
this.field.set('label', castToNullIfUndef(this.props.label))
|
||||
this.field.set('placeholder', castToNullIfUndef(this.props.placeholder))
|
||||
}
|
||||
|
||||
@action.bound
|
||||
renderChildren(){
|
||||
let ourProps = this.winnowProps()
|
||||
let elem = React.cloneElement(this.props.children as React.ReactElement<any>,
|
||||
{...ourProps, ...this.field.bind() })
|
||||
return elem
|
||||
|
||||
}
|
||||
|
||||
///Removes the properties we don't want to put into the input element
|
||||
@action.bound
|
||||
winnowProps(): ReactInputProps & InputHTMLAttributes<HTMLInputElement> {
|
||||
let ourProps = {...this.props}
|
||||
delete ourProps.field
|
||||
delete ourProps.value
|
||||
return ourProps
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
if (this.props.children)
|
||||
{
|
||||
return this.renderChildren()
|
||||
}
|
||||
else {
|
||||
return <input {...this.winnowProps()} {...this.field.bind()}/>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default observer(ReactInput)
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ReactInput no children passed in gets removed properly 1`] = `
|
||||
<form>
|
||||
<button
|
||||
onClick={[Function]}
|
||||
/>
|
||||
</form>
|
||||
`;
|
|
@ -17,47 +17,31 @@ export interface NonprofitInfoFormProps
|
|||
export const FieldDefinitions : Array<FieldDefinition> = [
|
||||
{
|
||||
name: 'organization_name',
|
||||
label: 'registration.wizard.nonprofit.name.label',
|
||||
placeholder: 'registration.wizard.nonprofit.name.placeholder',
|
||||
type: 'text',
|
||||
validators: [Validations.isFilled]
|
||||
},
|
||||
{
|
||||
name: 'website',
|
||||
label: 'registration.wizard.nonprofit.website.label',
|
||||
placeholder: 'registration.wizard.nonprofit.website.placeholder',
|
||||
validators: [Validations.optional(Validations.isUrl)]
|
||||
},
|
||||
{
|
||||
name: 'org_email',
|
||||
label: 'registration.wizard.nonprofit.email.label',
|
||||
placeholder: 'registration.wizard.nonprofit.email.placeholder',
|
||||
validators: [Validations.optional(Validations.isEmail)]
|
||||
},
|
||||
{
|
||||
name: 'org_phone',
|
||||
label: 'registration.wizard.nonprofit.phone.label',
|
||||
placeholder: 'registration.wizard.nonprofit.phone.placeholder',
|
||||
type: "tel"
|
||||
},
|
||||
{
|
||||
name: 'city',
|
||||
label: 'registration.wizard.nonprofit.city.label',
|
||||
placeholder: 'registration.wizard.nonprofit.city.placeholder',
|
||||
validators: [Validations.isFilled]
|
||||
},
|
||||
{
|
||||
name: 'state',
|
||||
label: 'registration.wizard.nonprofit.state.label',
|
||||
placeholder: 'registration.wizard.nonprofit.state.placeholder',
|
||||
type: 'text',
|
||||
validators: [Validations.isFilled]
|
||||
|
||||
},
|
||||
{
|
||||
name: 'zip',
|
||||
label: 'registration.wizard.nonprofit.zip.label',
|
||||
placeholder: 'registration.wizard.nonprofit.zip.placeholder',
|
||||
validators: [Validations.isFilled]
|
||||
}
|
||||
]
|
||||
|
@ -67,17 +51,33 @@ class NonprofitInfoForm extends React.Component<NonprofitInfoFormProps & Injecte
|
|||
|
||||
render() {
|
||||
return <fieldset >
|
||||
<BasicField field={this.props.form.$("organization_name")}/>
|
||||
<BasicField field={this.props.form.$('website')}/>
|
||||
<BasicField field={this.props.form.$("organization_name")}
|
||||
label={this.props.intl.formatMessage({id:'registration.wizard.nonprofit.name.label' })}
|
||||
placeholder={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.name.placeholder'})}
|
||||
/>
|
||||
|
||||
<BasicField field={this.props.form.$('website')}
|
||||
label={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.website.label'})}
|
||||
placeholder={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.website.placeholder'})}/>
|
||||
<TwoColumnFields>
|
||||
<BasicField field={this.props.form.$('org_email')}/>
|
||||
<BasicField field={this.props.form.$('org_phone')}/>
|
||||
<BasicField field={this.props.form.$('org_email')}
|
||||
label={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.email.label'})}
|
||||
placeholder={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.email.placeholder'})}/>
|
||||
<BasicField field={this.props.form.$('org_phone')}
|
||||
label={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.phone.label'})}
|
||||
placeholder={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.phone.placeholder'})}/>
|
||||
</TwoColumnFields>
|
||||
|
||||
<ThreeColumnFields>
|
||||
<BasicField field={this.props.form.$('city')}/>
|
||||
<BasicField field={this.props.form.$('state')}/>
|
||||
<BasicField field={this.props.form.$('zip')}/>
|
||||
<BasicField field={this.props.form.$('city')}
|
||||
label={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.city.label'})}
|
||||
placeholder={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.city.placeholder'})}/>
|
||||
<BasicField field={this.props.form.$('state')}
|
||||
label={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.state.label'})}
|
||||
placeholder={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.state.placeholder'})}/>
|
||||
<BasicField field={this.props.form.$('zip')}
|
||||
label={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.zip.label' })}
|
||||
placeholder={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.zip.placeholder'})}/>
|
||||
</ThreeColumnFields>
|
||||
<ProgressableButton onClick={this.props.form.onSubmit} className="button" disabled={!this.props.form.isValid} buttonText={this.props.intl.formatMessage({id: this.props.buttonText})}
|
||||
inProgress={this.props.form.submitting || this.props.form.container().submitting} disableOnProgress={true}/>
|
||||
|
|
|
@ -175,24 +175,6 @@ export class InnerRegistrationWizard extends React.Component<RegistrationWizardP
|
|||
this.form.signinApi = this.props.ApiManager.get(WebUserSignInOut)
|
||||
}
|
||||
|
||||
//set up labels
|
||||
let label: {[props:string]: string} = {
|
||||
'nonprofitTab[organization_name]': "registration.wizard.nonprofit.name.label",
|
||||
"nonprofitTab[website]": 'registration.wizard.nonprofit.website.label',
|
||||
"nonprofitTab[org_email]": 'registration.wizard.nonprofit.email.label',
|
||||
'nonprofitTab[org_phone]': 'registration.wizard.nonprofit.phone.label',
|
||||
'nonprofitTab[city]': 'registration.wizard.nonprofit.city.label',
|
||||
'nonprofitTab[state]': 'registration.wizard.nonprofit.state.label',
|
||||
'nonprofitTab[zip]': 'registration.wizard.nonprofit.zip.label',
|
||||
'userTab[name]': 'registration.wizard.contact.name.label',
|
||||
'userTab[email]': 'registration.wizard.contact.email.label',
|
||||
'userTab[password]': 'registration.wizard.contact.password.label',
|
||||
'userTab[password_confirmation]': 'registration.wizard.contact.password_confirmation.label'
|
||||
}
|
||||
for (let key in label){
|
||||
this.form.$(key).set('label', this.props.intl.formatMessage({id: label[key]}))
|
||||
}
|
||||
|
||||
return <Wizard wizardState={this.registrationWizardState} disableTabs={this.form.submitting}>
|
||||
<NonprofitInfoPanel tab={this.registrationWizardState.tabsByName['nonprofitTab']}
|
||||
buttonText="registration.wizard.next"/>
|
||||
|
|
|
@ -12,8 +12,6 @@ import {areWeOrAnyParentSubmitting} from "../../lib/houdini_form";
|
|||
export const FieldDefinitions : Array<FieldDefinition> = [
|
||||
{
|
||||
name: 'name',
|
||||
label: 'registration.wizard.contact.name.label',
|
||||
placeholder: 'registration.wizard.contact.name.placeholder',
|
||||
validators: [Validations.isFilled]
|
||||
},
|
||||
{
|
||||
|
@ -24,14 +22,12 @@ export const FieldDefinitions : Array<FieldDefinition> = [
|
|||
},
|
||||
{
|
||||
name: 'password',
|
||||
label: 'registration.wizard.contact.password.label',
|
||||
type: 'password',
|
||||
validators: [Validations.isFilled],
|
||||
related: ['userTab.password_confirmation']
|
||||
},
|
||||
{
|
||||
name: 'password_confirmation',
|
||||
label: 'registration.wizard.contact.password_confirmation.label',
|
||||
type: 'password',
|
||||
validators: [Validations.shouldBeEqualTo("userTab.password")]
|
||||
}
|
||||
|
@ -50,12 +46,22 @@ class UserInfoForm extends React.Component<UserInfoFormProps & InjectedIntlProps
|
|||
render() {
|
||||
return <fieldset>
|
||||
<TwoColumnFields>
|
||||
<BasicField field={this.props.form.$("name")}/>
|
||||
<BasicField field={this.props.form.$('email')}/>
|
||||
<BasicField field={this.props.form.$("name")}
|
||||
label={
|
||||
this.props.intl.formatMessage({id: "registration.wizard.contact.name.label"})}
|
||||
placeholder={this.props.intl.formatMessage({id: "registration.wizard.contact.name.placeholder"})}/>
|
||||
<BasicField field={this.props.form.$('email')}
|
||||
label={this.props.intl.formatMessage({id: "registration.wizard.contact.email.label"})}
|
||||
placeholder={this.props.intl.formatMessage({id: "registration.wizard.contact.email.placeholder"})}
|
||||
/>
|
||||
</TwoColumnFields>
|
||||
|
||||
<BasicField field={this.props.form.$('password')}/>
|
||||
<BasicField field={this.props.form.$('password_confirmation')}/>
|
||||
<BasicField field={this.props.form.$('password')}
|
||||
label={this.props.intl.formatMessage({id:'registration.wizard.contact.password.label'})}
|
||||
/>
|
||||
<BasicField field={this.props.form.$('password_confirmation')}
|
||||
label={this.props.intl.formatMessage({id:'registration.wizard.contact.password_confirmation.label'})}
|
||||
/>
|
||||
|
||||
|
||||
<ProgressableButton onClick={this.props.form.onSubmit}
|
||||
|
|
|
@ -23,13 +23,11 @@ export interface SessionLoginFormProps
|
|||
export const FieldDefinitions : Array<FieldDefinition> = [
|
||||
{
|
||||
name: 'email',
|
||||
label: 'email',
|
||||
type: 'text',
|
||||
validators: [Validations.isFilled]
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
label: 'password',
|
||||
type: 'password',
|
||||
validators: [Validations.isFilled]
|
||||
}
|
||||
|
@ -100,20 +98,14 @@ class InnerSessionLoginForm extends React.Component<SessionLoginFormProps & Inje
|
|||
if(!this.form.signinApi){
|
||||
this.form.signinApi = this.props.ApiManager.get(WebUserSignInOut)
|
||||
}
|
||||
let label: {[props:string]: string} = {
|
||||
'email': "login.email",
|
||||
"password": 'login.password',
|
||||
}
|
||||
|
||||
for (let key in label){
|
||||
this.form.$(key).set('label', this.props.intl.formatMessage({id: label[key]}))
|
||||
}
|
||||
|
||||
let errorDiv = !this.form.isValid ? <div className="form-group has-error"><div className="help-block" role="alert">{(this.form as any).error}</div></div> : ''
|
||||
|
||||
return <form onSubmit={this.form.onSubmit}>
|
||||
<BasicField field={this.form.$('email')}/>
|
||||
<BasicField field={this.form.$('password')}/>
|
||||
<BasicField field={this.form.$('email')}
|
||||
label={this.props.intl.formatMessage({id: 'login.email'})}/>
|
||||
<BasicField field={this.form.$('password')}
|
||||
label={this.props.intl.formatMessage({id: 'login.password'})}/>
|
||||
{errorDiv}
|
||||
<div className={'form-group'}>
|
||||
<ProgressableButton onClick={this.form.onSubmit} className="button" disabled={!this.form.isValid || this.form.submitting} inProgress={this.form.submitting}
|
||||
|
|
30
package-lock.json
generated
30
package-lock.json
generated
|
@ -5697,9 +5697,9 @@
|
|||
"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0="
|
||||
},
|
||||
"hoist-non-react-statics": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.0.tgz",
|
||||
"integrity": "sha512-6Bl6XsDT1ntE0lHbIhr4Kp2PGcleGZ66qu5Jqk8lc0Xc/IeG6gVLmwUGs/K0Us+L8VWoKgj0uWdPMataOsm31w==",
|
||||
"version": "2.5.5",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz",
|
||||
"integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==",
|
||||
"dev": true
|
||||
},
|
||||
"home-or-tmp": {
|
||||
|
@ -8900,19 +8900,19 @@
|
|||
}
|
||||
},
|
||||
"mobx": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/mobx/-/mobx-4.2.1.tgz",
|
||||
"integrity": "sha1-3UGQ2vG0PUGjoihYUlP5lwsKJ90=",
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/mobx/-/mobx-4.3.1.tgz",
|
||||
"integrity": "sha1-M05aq0kWsdQ/D682BaZLG0s8y40=",
|
||||
"dev": true
|
||||
},
|
||||
"mobx-react": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/mobx-react/-/mobx-react-5.1.2.tgz",
|
||||
"integrity": "sha1-7FwtKaHfgj29GzfiFPo2oJBwVOI=",
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/mobx-react/-/mobx-react-5.2.3.tgz",
|
||||
"integrity": "sha512-OuSlF2nJEa1PGookZcZnINbvEK4iWNNYiqUh6aebk2AkWxj3sG8OafDOQMcMYApQALTHRsrBIjOx/K8TFxcz7w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"hoist-non-react-statics": "2.5.0",
|
||||
"react-lifecycles-compat": "3.0.3"
|
||||
"hoist-non-react-statics": "2.5.5",
|
||||
"react-lifecycles-compat": "3.0.4"
|
||||
}
|
||||
},
|
||||
"mobx-react-devtools": {
|
||||
|
@ -8922,7 +8922,7 @@
|
|||
"dev": true
|
||||
},
|
||||
"mobx-react-form": {
|
||||
"version": "github:houdiniproject/mobx-react-form#63a163397102d86745b7ac381d42b794ec172231",
|
||||
"version": "github:houdiniproject/mobx-react-form#8421c456a88cd3d7f887168a8228bb1a04911e7d",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lodash": "4.17.10"
|
||||
|
@ -11584,9 +11584,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"react-lifecycles-compat": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.3.tgz",
|
||||
"integrity": "sha512-bOr65SSYgxDgDNqLnDqt+gropXGPNB1Wbyys4tOYiNuP/qYWC4qFM9XH1ruzq+tT6EjE29pJsCr19rclKtpUEg==",
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==",
|
||||
"dev": true
|
||||
},
|
||||
"react-reconciler": {
|
||||
|
|
|
@ -54,8 +54,8 @@
|
|||
"less": "^3.0.4",
|
||||
"less-loader": "^4.1.0",
|
||||
"lodash": "^4.17.5",
|
||||
"mobx": "^4.2.0",
|
||||
"mobx-react": "^5.0.0",
|
||||
"mobx": "^4.3.1",
|
||||
"mobx-react": "^5.2.3",
|
||||
"mobx-react-devtools": "^5.0.1",
|
||||
"mobx-react-form": "github:houdiniproject/mobx-react-form#our_fix",
|
||||
"no-scroll": "^2.1.0",
|
||||
|
|
16
types/mobx-react-form/index.d.ts
vendored
16
types/mobx-react-form/index.d.ts
vendored
|
@ -72,7 +72,7 @@ export declare class Field implements Base, FieldProperties, FieldMethods, Field
|
|||
|
||||
$(fieldName: string): Field;
|
||||
|
||||
add(obj: any): any;
|
||||
add(obj:{FieldDefinition}): any;
|
||||
|
||||
bind(): object;
|
||||
|
||||
|
@ -82,7 +82,7 @@ export declare class Field implements Base, FieldProperties, FieldMethods, Field
|
|||
|
||||
container(): Form |Field
|
||||
|
||||
del(key: any);
|
||||
del(path?: string);
|
||||
|
||||
each(callback: (i: Field) => void);
|
||||
|
||||
|
@ -173,6 +173,7 @@ interface FieldHandlers {
|
|||
|
||||
interface FieldDefinition {
|
||||
name: string
|
||||
key?: string
|
||||
label?: string
|
||||
value?: any
|
||||
default?: any
|
||||
|
@ -253,12 +254,13 @@ interface FormInitializer{
|
|||
|
||||
interface initializationDefinition {
|
||||
fields?:FieldDefinitions[]
|
||||
hooks?: FormHooks
|
||||
}
|
||||
|
||||
export class Form implements Base {
|
||||
|
||||
|
||||
constructor(definition:initializationDefinition, options?:any)
|
||||
constructor(definition?:initializationDefinition, options?:any)
|
||||
plugins(): void
|
||||
setup(): any
|
||||
onInit(): void
|
||||
|
@ -269,7 +271,7 @@ export class Form implements Base {
|
|||
|
||||
$(fieldName: string): Field;
|
||||
|
||||
add(obj: any): any;
|
||||
add(obj:FieldDefinition): any;
|
||||
|
||||
check(computed: string, deep?: boolean): boolean;
|
||||
|
||||
|
@ -292,7 +294,7 @@ export class Form implements Base {
|
|||
|
||||
map(callback: (i: Field) => void);
|
||||
|
||||
observe(obj: any);
|
||||
observe(...obj: any)
|
||||
|
||||
select(path: string): Field;
|
||||
|
||||
|
@ -304,10 +306,12 @@ export class Form implements Base {
|
|||
update(obj: any): void;
|
||||
|
||||
readonly submitting: boolean;
|
||||
readonly isValid:boolean;
|
||||
|
||||
protected validator :any
|
||||
|
||||
readonly isValid :boolean;
|
||||
readonly size:number
|
||||
|
||||
|
||||
}
|
||||
|
@ -327,7 +331,7 @@ interface SharedFieldFormMethods {
|
|||
has(key:string):boolean
|
||||
map(callback:(i:Field) => void)
|
||||
each(callback:(i:Field) => void)
|
||||
add(obj:any):any
|
||||
add(obj:FieldDefinition): any;
|
||||
del(key:any)
|
||||
observe(obj:any)
|
||||
intercept(obj:any)
|
||||
|
|
Loading…
Reference in a new issue