We are integrating AOR(version 1.2.3) with existing Application.
we are trying to provide Edit Feature in that when we give
<---Field> Components its working fine
also able to see SAVE button
but
when it <---Input> Components
no SAVE button is visible and Component does take inputs.
Code when
Field Components are used
import React, { Component } from 'react';
import {
Components
} from 'admin-on-rest';
const CustomerEdit = (props) => (
<Edit {...this.props}>
<TabbedForm>
<FormTab label="Profile">
<TextField source="firstName" />
<TextField source="middleName" />
<TextField source="lastName" />
</FormTab>
<FormTab label="Address">
<ReferenceManyField addLabel={false} reference="CustomerAddresses" target="customerProfileId">
<Datagrid>
<EditButton/>
<TextField source="id" />
<TextField source="line1" />
<TextField source="pinCode" />
</Datagrid>
</ReferenceManyField>
</FormTab>
</TabbedForm>
</Edit>
);
export default CustomerEdit;
Code when
Input
Components are used
import React, { Component } from 'react';
import {
Components
} from 'admin-on-rest';
const CustomerEdit = (props) => (
<Edit {...this.props}>
<TabbedForm>
<FormTab label="Profile">
<TextInput source="firstName" />
<TextInput source="middleName" />
<TextInput source="lastName" />
</FormTab>
<FormTab label="Address">
<ReferenceManyField addLabel={false} reference="CustomerAddresses" target="customerProfileId">
<Datagrid>
<EditButton/>
<TextInput source="id" />
<TextInput source="line1" />
<TextInput source="pinCode" />
</Datagrid>
</ReferenceManyField>
</FormTab>
</TabbedForm>
</Edit>
);
export default CustomerEdit;
This is App.js
import React from 'react';
import PropTypes from 'prop-types';
// redux, react-router, redux-form, saga, and material-ui
// form the 'kernel' on which admin-on-rest runs
import { combineReducers, createStore, compose, applyMiddleware } from 'redux'
import { Provider } from 'react-redux'
import createHistory from 'history/createHashHistory'
import { Switch, Route } from 'react-router-dom'
import { ConnectedRouter, routerReducer, routerMiddleware } from 'react-router-redux';
import { reducer as formReducer } from 'redux-form';
import createSagaMiddleware from 'redux-saga';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
// prebuilt admin-on-rest features
import {
adminReducer,
localeReducer,
crudSaga,
TranslationProvider,
} from 'admin-on-rest';
import restClient from './restClient';
import GenericList from './ui/List';
import CustomerEdit from './ui/views/customer/customerEdit';
const reducer = combineReducers({
admin: adminReducer([{ name: 'CustomerProfiles' },
{ name: 'CustomerAddresses' }]),
locale: localeReducer(),
form: formReducer,
routing: routerReducer,
});
const sagaMiddleware = createSagaMiddleware();
const history = createHistory();
const store = createStore(reducer, undefined, compose(
applyMiddleware(sagaMiddleware, routerMiddleware(history)),
window.devToolsExtension ? window.devToolsExtension() : f => f,
));
sagaMiddleware.run(crudSaga(restClient));
const App = () => (
<Provider store={store}>
<TranslationProvider messages={messages}>
<ConnectedRouter history={history}>
<MuiThemeProvider>
<Switch>
<Route exact path="/profile"
hasCreate render={
(routeProps) => <GenericList resource="CustomerProfiles" {...routeProps} />
} />
<Route exact path="/profile/:id"
hasEdit render={
(routeProps) => <CustomerEdit resource="CustomerProfiles" {...routeProps} />
} />
</Switch>
</MuiThemeProvider>
</ConnectedRouter>
</TranslationProvider>
</Provider>
);
export default App
This in case of Input Components
No Data from Backend for CustomerAddress and also no Save Button
This in Case of Field Component
when we use <---FIELD/> Component
Don't you have an error in the console about ReferenceManyInput ? This component does not exist.
I checked the documentation and we indeed included it in the Resources chapter. It will be fixed soon.
For referencing many other resources, you should use the ReferenceArrayInput. However, it does not support Datagrids. There are not components allowing you to edit related resources yet.
Related
I've reduced this to a very simple case for ease of discussion. I have a simple create form with 1 field and 1 button. I would like the button to set the value of the TextInput to "Hello" without submitting the form. How is this possible in admin on rest? eg:
export const TestCreate = (props) => (
<Create title={<TestTitle />} {...props}>
<SimpleForm>
<TextInput source="title" />
<TitleSetterButton />
</SimpleForm>
</Create>
);
Been struggling with this for a while - it should be simple so hopefully there's an easy answer.
I was able to setup a Sample form using their example application
// in src/posts.js
import React from 'react';
import { List, Edit, Create, Datagrid, ReferenceField, TextField, EditButton, DisabledInput, LongTextInput, ReferenceInput, required, SelectInput, SimpleForm, TextInput } from 'admin-on-rest';
import FlatButton from 'material-ui/FlatButton';
export const PostList = (props) => (
<List {...props}>
<Datagrid>
<TextField source="id" />
<ReferenceField label="User" source="userId" reference="users">
<TextField source="name" />
</ReferenceField>
<TextField source="title" />
<TextField source="body" />
<EditButton />
</Datagrid>
</List>
);
const PostTitle = ({ record }) => {
return <span>Post {record ? `"${record.title}"` : ''}</span>;
};
export class Testing extends React.Component {
render() {
return <input type="text" />
}
}
export class PostCreate extends React.Component {
componentDidMount() {
console.log(this)
}
constructor(props) {
super(props);
this.handleCustomClick = this.handleCustomClick.bind(this);
// this.fieldOptions = this.fieldOptions.bind(this);
}
handleCustomClick() {
this.fields.title.handleInputBlur("tarun lalwani");
this.fields.body.handleInputBlur("this is how you change it!");
}
render () {
let refOptions = {ref: (e) => {
if (e && e.constructor && e.props && e.props.name) {
this.fields = this.fields || {};
this.fields[e.props.name] = e;
}
}}
return (
<Edit title={<PostTitle />} {...this.props}>
<SimpleForm>
<DisabledInput source="id" />
<ReferenceInput label="User" source="userId" reference="users" validate={required}>
<SelectInput optionText="name" />
</ReferenceInput>
<TextInput source="title" options={refOptions}/>
<LongTextInput source="body" options={refOptions}/>
<FlatButton primary label="Set Value" onClick={this.handleCustomClick} />
</SimpleForm>
</Edit>
);
}
}
Before click of the button
After clicking Set Value
And then after clicking Save you can see the actual changed values get posted
I have added the material-ui/Checkbox component in admin-on-rest create form with source attribute. But after I click save button, I could not see the checkbox value in posted data.
But I can see 'title' and 'body' fields value in posted data. Can someone please tell, Why this code is not working?
Here is my sample code:
export const PostCreate = (props) => (
<Create {...props} >
<SimpleForm>
<TextInput source="title" />
<LongTextInput source="body" />
<Checkbox
label="Label on the left"
labelPosition="left"
source="test"
value="yes"
/>
</SimpleForm></Create>
);
Sure Checkbox is not a react-on-admin component. Please use BooleanInput
The BooleanInput.js module from rect-admin, Switch is replaced with Checkbox:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import FormControlLabel from '#material-ui/core/FormControlLabel'
import FormGroup from '#material-ui/core/FormGroup'
import Checkbox from '#material-ui/core/Checkbox'
import { addField, FieldTitle } from 'ra-core'
const sanitizeRestProps = ({
alwaysOn,
basePath,
component,
defaultValue,
formClassName,
initializeForm,
input,
isRequired,
label,
locale,
meta,
options,
optionText,
optionValue,
record,
resource,
allowEmpty,
source,
textAlign,
translate,
translateChoice,
...rest
}) => rest
export class CheckboxInput extends Component {
handleChange = (event, value) => {
this.props.input.onChange(value)
}
render() {
const {
className,
input,
isRequired,
label,
source,
resource,
options,
...rest
} = this.props
return (
<FormGroup className={className} {...sanitizeRestProps(rest)}>
<FormControlLabel
control={
<Checkbox
color="primary"
checked={!!input.value}
onChange={this.handleChange}
{...options}
/>
}
label={
<FieldTitle
label={label}
source={source}
resource={resource}
isRequired={isRequired}
/>
}
/>
</FormGroup>
)
}
}
CheckboxInput.propTypes = {
className: PropTypes.string,
input: PropTypes.object,
isRequired: PropTypes.bool,
label: PropTypes.string,
resource: PropTypes.string,
source: PropTypes.string,
options: PropTypes.object,
}
CheckboxInput.defaultProps = {
options: {},
}
export default addField(CheckboxInput)
I have the following Edit component:
const UserEdit = (props) => (
<Edit {...props}>
<TabbedForm>
<FormTab label="Main">
<TextInput source="var1" />
<TextInput source="var2" />
<TextInput source="var3" />
</FormTab>
<FormTab label="Images">
<ImageUploadComponant />
<ReferenceManyField label="Images" reference="images" target="user_id">
<Datagrid>
<ImageField source="url" />
<DeleteButton />
</Datagrid>
</ReferenceManyField>
</FormTab>
</TabbedForm>
</Edit>
);
The ImageUploadComponant is juste a componant that enable the user to upload a file, and it creates a new object on the API related to the ReferenceManyField :
class ImageUpload extends Component {
onDrop = async files => {
/* Uploading the file */
};
render() {
return (
/* A componant with an upload field */
);
}
}
ImageUpload.propTypes = {
push: PropTypes.func,
record: PropTypes.object,
showNotification: PropTypes.func,
};
export default connect(null, {
showNotification: showNotificationAction,
push: pushAction,
})(ImageUpload);
After the /* Uploading the file */ block, I would like to refresh the ReferenceManyField so the fresh uploaded image is shown.
I guess I have to put some kind of redux / sagas message, but I didn't manage to perform it. Any idea ?
I would like to make a custom button that would be used to fetch. I want the button to be usable like this:
export const LogList = (props) => (
<List {...props} perPage={100} title="Logs and Reports" filters={< FileFilter/>}>
<Datagrid>
<TextField source="inputfile" label="Input File" />
<TextField source="cycle" label="Cycle" />
<TextField source="job" label="Job" />
<TextField source="name" label="File Name" />
<ShowButton/>
<JobCancel/>
</Datagrid>
</List>
);
Where is my button is <JobCancel/> up above (similar to how ShowButton is implemented). I want the button to fetch(controller_service/archivedfiles/${id}, { method: 'DELETE', body:{} }); on click.
Is something like this possible?
P.S. I am new to Admin on rest
You can also find an example for custom actions in the demo repository for reviews (accept, reject): https://github.com/marmelab/admin-on-rest-demo/tree/master/src/reviews
Misread your question. So am editing my answer.
I have custom button for my list view.
It's a straightforward Redux connected component.
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import RaisedButton from 'material-ui/RaisedButton';
import { editorAssign as editorAssignAction} from '../customActions/EditorAssignActions'
import styles from '../styles/styles'
class EditorAssignButton extends Component {
constructor(props){
super(props);
this.state = { disabled: false };
}
handleClick = () => {
const { editorAssign, record } = this.props
editorAssign(record.id) //call the action
this.setState({
disabled: true
})
}
render() {
const editorAssignStyle = styles.editorAssignStyle;
return (<RaisedButton label='Add To Edit'
onClick={this.handleClick}
disabled={ this.state.disabled }
primary={true}
/>)
}
}
EditorAssignButton.propTypes = {
editorAssign: PropTypes.func,
record: PropTypes.object
}
export default connect(null, {
editorAssign: editorAssignAction
})(EditorAssignButton)
AOR has documentation on how to write custom actions and trigger side effects with Sagas.
https://marmelab.com/admin-on-rest/Actions.html
DELETE is an action available with AOR Rest so your requirement should be quite standard.
Here is the EditorAssign view. It is a straightforward list and datagrid component
import React from 'react';
import { ReferenceField,
ChipField,
SelectInput,
ReferenceInput,
TextField,
List,
Filter,
Datagrid} from 'admin-on-rest';
import AssignTaleEditToSelf from '../buttons/AssignTaleEditToSelf'
const EditorAssignView = (props) => {
return (
<List {...props} title="Fresh Tales" perPage={20} sort={{ field: 'id', order: 'ASC' }} filter={{"status": "NEW"}} filters={ <EditorFilter /> } >
<Datagrid >
<TextField source="id" label="id" style={{ textAlign: 'center'}} />
<TextField source="taleTitle" label="Title" />
<TextField source="taleText" label="Content" style={{maxWidth: '150px'}} />
<ReferenceField label="Writer" source="writer_id" reference="appUsers">
<ChipField source="name" />
</ReferenceField>
<AssignTaleEditToSelf label="Assign To Self" />
</CustomDatagrid>
</List>
)
}
}
I need to customize the list title, but to allow it in diff. languages.
I try:
<List title='Hi there' ...>
and title is changed as expected BUT how do I make the string configurable from a file?
<List title={translate('myroot.list.header') ...>
doesn't work...
Try with a custom title component:
import { translate } from 'admin-on-rest';
const ListTitle = translate(({ translate }) => <span>{translate('my.title')}</span>);
<List title={<ListTitle />} >
hope that it will help you:
customMessages.js
export const customMessages = {
titles: {
one: 'First Title',
two: 'Second Title',
},
}
App.js
import { englishMessages } from 'admin-on-rest';
import { customMessages } from './customMessages';
const messages = {
'en': {...englishMessages, ...customMessages},
};
resources.js
export const ResourceList = (props) => (
<List {...props} title="titles.one">
<Datagrid>
<TextField source="id" />
<TextField source="text" />
<EditButton />
<DeleteButton />
</Datagrid>
</List>
);
Replace next to your names:
resources.js
ResourceList