Created
November 30, 2016 18:09
-
-
Save anselmdk/c042819dce6e55587fbae12088e3dcb0 to your computer and use it in GitHub Desktop.
SilverStripe 4 React Form Schema on frontend POC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react' | |
import ReactDOM from 'react-dom' | |
import Field from './Field'; | |
import FormBuilder from '../../../framework/admin/client/src/components/FormBuilder/FormBuilder' | |
import Form from '../../../framework/admin/client/src/components/Form/Form'; | |
const schemaUrl = '/formschematest/schema/TestForm'; | |
$.get(schemaUrl, function(data) { | |
const props = { | |
form: 'MyForm', | |
schema: data, | |
baseFormComponent: Form, | |
baseFieldComponent: Field | |
}; | |
ReactDOM.render( | |
<div> | |
<FormBuilder {...props} /> | |
</div>, | |
document.getElementById('approot') | |
); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use SilverStripe\Forms\FormFactory; | |
use SilverStripe\Forms\DefaultFormFactory; | |
use SilverStripe\Control\Controller; | |
/** | |
* AppFormFactory | |
* | |
* @author Anselm Christophersen <[email protected]> | |
* @date November 2016 | |
*/ | |
class AppFormFactory extends DefaultFormFactory { | |
public function getForm(Controller $controller, $name = FormFactory::DEFAULT_NAME, $context = []) | |
{ | |
$form = parent::getForm($controller, $name, $context); | |
return $form; | |
} | |
protected function getFormFields(Controller $controller, $name, $context = []) | |
{ | |
$fields = $context['Record']->scaffoldFormFields(); | |
$this->invokeWithExtensions('updateFormFields', $fields, $controller, $name, $context); | |
return $fields; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Component } from 'react'; | |
import TextField from 'components/TextField/TextField'; | |
import HiddenField from 'components/HiddenField/HiddenField'; | |
import CheckboxField from 'components/CheckboxField/CheckboxField'; | |
import CheckboxSetField from 'components/CheckboxSetField/CheckboxSetField'; | |
import OptionsetField from 'components/OptionsetField/OptionsetField'; | |
import GridField from 'components/GridField/GridField'; | |
import SingleSelectField from 'components/SingleSelectField/SingleSelectField'; | |
class Field extends Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
value: null | |
}; | |
} | |
onChange(event, options) { | |
this.setState({ | |
value: options.value | |
}); | |
} | |
render() { | |
let value = this.state.value; | |
if (!value) { | |
value = this.props.value; | |
} | |
const props = {...this.props, ...{ | |
value: value, | |
onChange: this.onChange.bind(this) | |
}}; | |
switch (this.props.type) { | |
case 'Text': | |
case 'DateTime': | |
return <TextField {...props} /> | |
case 'Hidden': | |
return <HiddenField {...props} /> | |
case 'SingleSelect': | |
return <SingleSelectField {...props} /> | |
//case 'Custom': | |
// return this.components.GridField; | |
//case 'Structural': | |
// return this.components.CompositeField; | |
case 'Boolean': | |
return <CheckboxField {...props} /> | |
// return this.components.CheckboxField; | |
//case 'MultiSelect': | |
// return this.components.CheckboxSetField; | |
default: | |
return <div> | |
{this.props.type} | |
</div>; | |
} | |
} | |
} | |
export default Field; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use SilverStripe\Control\HTTPResponse; | |
use SilverStripe\Control\HTTPRequest; | |
use SilverStripe\Core\Convert; | |
use SilverStripe\Core\Injector\Injector; | |
use SilverStripe\Forms\DefaultFormFactory; | |
use SilverStripe\Forms\Form; | |
/** | |
* FormSchemaTestController | |
* Much this is taken from {@see LeftAndMain} | |
* | |
* @author Anselm Christophersen <[email protected]> | |
* @date November 2016 | |
*/ | |
class FormSchemaTestController extends \SilverStripe\Control\Controller { | |
/** | |
* @var array | |
*/ | |
private static $allowed_actions = array( | |
'schema', | |
'TestForm' | |
); | |
private static $url_handlers = [ | |
'GET schema/$FormName/$ItemID' => 'schema' | |
]; | |
private static $dependencies = [ | |
'schema' => '%$FormSchema' | |
]; | |
/** | |
* Gets a JSON schema representing the current edit form. | |
* | |
* WARNING: Experimental API. | |
* | |
* @param HTTPRequest $request | |
* @return HTTPResponse | |
*/ | |
public function schema($request) { | |
$response = $this->getResponse(); | |
$formName = $request->param('FormName'); | |
$itemID = $request->param('ItemID'); | |
if (!$formName) { | |
return (new HTTPResponse('Missing request params', 400)); | |
} | |
if(!$this->hasMethod("get{$formName}")) { | |
return (new HTTPResponse('Form not found', 404)); | |
} | |
if(!$this->hasAction($formName)) { | |
return (new HTTPResponse('Form not accessible', 401)); | |
} | |
$form = $this->{"get{$formName}"}($itemID); | |
$response->addHeader('Content-Type', 'application/json'); | |
$response->setBody(Convert::raw2json($this->getSchemaForForm($form))); | |
return $response; | |
} | |
/** | |
* Returns a representation of the provided {@link Form} as structured data, | |
* based on the request data. | |
* | |
* @param Form $form | |
* @param String $id Optional, will default to the current request URL | |
* @return array | |
*/ | |
protected function getSchemaForForm(Form $form, $id = null) { | |
$request = $this->getRequest(); | |
$id = $id ? $id : $request->getURL(); | |
$return = null; | |
// Valid values for the "X-Formschema-Request" header are "schema" and "state". | |
// If either of these values are set they will be stored in the $schemaParst array | |
// and used to construct the response body. | |
if ($schemaHeader = $request->getHeader('X-Formschema-Request')) { | |
$schemaParts = array_filter(explode(',', $schemaHeader), function($value) { | |
$validHeaderValues = ['schema', 'state']; | |
return in_array(trim($value), $validHeaderValues); | |
}); | |
} else { | |
$schemaParts = ['schema']; | |
} | |
$return = ['id' => $id]; | |
if (in_array('schema', $schemaParts)) { | |
$return['schema'] = $this->schema->getSchema($form); | |
} | |
//this is uncommented for now as we want the values to be part of a request | |
//if (in_array('state', $schemaParts)) { | |
$return['state'] = $this->schema->getState($form); | |
//} | |
return $return; | |
} | |
public function getTestForm($id) | |
{ | |
$record = MyDataObject::get()->first(); | |
$scaffolder = Injector::inst()->get(AppFormFactory::class); | |
$form = $scaffolder->getForm($this, 'TestForm', [ | |
'Record' => $record, | |
]); | |
return $form; | |
} | |
public function TestForm() | |
{ | |
// Get ID either from posted back value, or url parameter | |
$request = $this->getRequest(); | |
$id = $request->param('ID') ?: $request->postVar('ID'); | |
return $this->getTestForm($id); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment