1 | # React Data Object Connect
|
2 |
|
3 | Utilities to connect AppframeWeb data objects to React components. Higher order components for class components, and hooks for function components.
|
4 |
|
5 | ## Getting Started
|
6 |
|
7 | ### Installation
|
8 |
|
9 | Install using npm
|
10 |
|
11 | ```
|
12 | npm install --save @olenbetong/react-data-object-connect
|
13 | ```
|
14 |
|
15 | or include the umd build in a script
|
16 |
|
17 | ```html
|
18 | <script src="https://unpkg.com/@olenbetong/react-data-object-connect@latest/dist/data-object-connect.umd.min.js"></script>
|
19 | ```
|
20 |
|
21 | ### Usage
|
22 |
|
23 | Use the connect and connectRow functions to create a higher order component that can be used to connect the data object to React components.
|
24 |
|
25 | The connect function will pass all records to the component in a property named `data`, while the connectRow passes all the fields in the current row as properties to the component.
|
26 |
|
27 | Example connecting to all records:
|
28 |
|
29 | ```jsx
|
30 | import React from "react";
|
31 | import { connect } from "@olenbetong/react-data-object-connect";
|
32 |
|
33 | const MyListComponent = props => (
|
34 | <ul>
|
35 | {props.data.map(item => (
|
36 | <li key={item.PrimKey}>{item.Title}</li>
|
37 | ))}
|
38 | </ul>
|
39 | );
|
40 |
|
41 | const MyConnectedList = connect(dsMyDataObject)(MyListComponent);
|
42 | ```
|
43 |
|
44 | Example connecting to a single record, and checking if it is modified:
|
45 |
|
46 | ```jsx
|
47 | import React from 'react';
|
48 | import { connectRow } from '@olenbetong/react-data-object-connect';
|
49 |
|
50 | const MyRecordComponent = (props) => (
|
51 | <p>
|
52 | {props.isDirty && <div>(Data not saved</div>)}
|
53 | {props.Title}
|
54 | </p>
|
55 | )
|
56 |
|
57 | const MyConnectedComponent = connectRow(dsMyDataObject)(MyRecordComponent);
|
58 | ```
|
59 |
|
60 | #### Properties
|
61 |
|
62 | Status properties passed to the component:
|
63 |
|
64 | - **canDelete** (bool) whether the data object allows deleting rows
|
65 | - **canUpdate** (bool) whether the data object allows updating rows
|
66 | - **canInsert** (bool) whether the data object allows inserting rows
|
67 | - **currentIndex** (int) current index selected
|
68 | - **isDirty** (bool) whether the currently selectec row has been modified
|
69 | - **isDeleting** (bool) whether the data object is currently deleting a row
|
70 | - **isLoading** (bool) whether the data object is currently loading data
|
71 | - **isSaving** (bool) whether the data object is currently saving a record
|
72 | - **loadError** (string) error message if the data failed to load
|
73 |
|
74 | Function properties passed to the component:
|
75 |
|
76 | - **onCancelEdit** used to cancel all changes made to the current record
|
77 | - **onCurrentIndexChange** used to select a row by index
|
78 | - **onEndEdit** used to attempt to save changes made to the current record
|
79 | - **onDeleteRow** used to delete a row. A component connected to the current row will always delete the current row, otherwise an index can be passed
|
80 | - **onFieldChange** used to update a field in the current row (name of field and value as parameters)
|
81 | - **onFieldsChange** used to update multiple fields in the current row (object with field names as keys, and values as values)
|
82 | - **onRefreshData** used to refresh data
|
83 | - **onRefreshRow** used to refresh only the current row
|
84 | - **onSetParameter** used to set a parameter on the data object
|
85 |
|
86 | ## Hooks
|
87 |
|
88 | If using a React with hooks, there are also data object hooks available.
|
89 |
|
90 | - useCurrentIndex(dataObject) - Returns only the current index
|
91 | - useCurrentRow(dataObject) - Returns the current record
|
92 | - useData(dataObject) - Returns an array with all records currently in the data object
|
93 | - useDirty(dataObject) - Returns a boolean indicating if the current row is dirty or not
|
94 | - useError(dataObject) - Returns any loading error message
|
95 | - useLoading(dataObject) - Returns a boolean indicating if the data object is loading or not
|
96 | - useStatus(dataObject) - Returns booleans indicating if the data object is saving or deleting records
|
97 | - usePermissions(dataObject) - Returns booleans indicating if the user can delete, insert or update records
|
98 |
|
99 | The above hooks uses the data objects internal state to pass data to the components. If you do not want to depend on the data objects current row or data storage, you can use the following hooks. They return data from the data object's data handler directly, and will not affect the data objects internal state.
|
100 |
|
101 | - useFetchData(dataObject, filter) - Returns data matching the filter
|
102 | - useFetchRecord(dataObject, filter) - Use if the filter is expected to only return a single row. If multiple rows are returned from the server, only the first record will be returned to the component.
|
103 |
|
104 | ### Examples
|
105 |
|
106 | #### Getting all state from the data object
|
107 |
|
108 | This will list all reacords in the data object, and create an editor for the current row.
|
109 |
|
110 | ```jsx
|
111 | import {
|
112 | useCurrentIndex,
|
113 | useCurrentRow,
|
114 | useData,
|
115 | useDirty,
|
116 | useError,
|
117 | useLoading,
|
118 | useStatus,
|
119 | usePermissions
|
120 | } from "@olenbetong/react-data-object-connect";
|
121 |
|
122 | function MyFunctionComponent(props) {
|
123 | const currentIndex = useCurrentIndex(dsMyDataObject);
|
124 | const myRecord = useCurrentRow(dsMyDataObject);
|
125 | const myRecords = useData(dsMyDataObject);
|
126 | const isDirty = useDirty(dsMyDataObject);
|
127 | const error = useError(dsMyDataObject);
|
128 | const isLoading = useLoading(dsMyDataObject);
|
129 | const { isDeleting, isSaving } = useStatus(dsMyDataObject);
|
130 | const { allowDelete, allowInsert, allowUpdate } = usePermissions(
|
131 | dsMyDataObject
|
132 | );
|
133 |
|
134 | return (
|
135 | <div>
|
136 | {isLoading && <i className="fa fa-spin fa-spinner" />}
|
137 | {error && <Error message={error} />}
|
138 | <MyEditor {...myRecord} isDirty={isDirty} />
|
139 | {myRecords.map(record => (
|
140 | <ListItem {...item} />
|
141 | ))}
|
142 | </div>
|
143 | );
|
144 | }
|
145 | ```
|
146 |
|
147 | #### Getting data from the data source without affecting the data object
|
148 |
|
149 | ```jsx
|
150 | import {
|
151 | useFetchData,
|
152 | useFetchRecord
|
153 | } from "@olenbetong/react-data-object-connect";
|
154 |
|
155 | function MyFunctionComponent(props) {
|
156 | const { isLoading, data, refresh } = useFetchData(
|
157 | dsMyDataObject,
|
158 | `[EntityCategory] = 1`
|
159 | );
|
160 |
|
161 | return (
|
162 | <div>
|
163 | {isLoading && <i className="fa fa-spin fa-spinner" />}
|
164 | {data.map(data => (
|
165 | <ListItem {...item} />
|
166 | ))}
|
167 | </div>
|
168 | );
|
169 | }
|
170 |
|
171 | function MyRecordComponent(props) {
|
172 | const { isLoading, record, refresh } = useFetchRecord(
|
173 | dsMyDataObject,
|
174 | `[EntityID] = ${props.id}`
|
175 | );
|
176 |
|
177 | return (
|
178 | <div>
|
179 | {isLoading && <Spinner />}
|
180 | <button onClick={refresh}>
|
181 | <i className="fa fa-refresh" /> Refresh
|
182 | </button>
|
183 | <MyEditor {...record} />
|
184 | </div>
|
185 | );
|
186 | }
|
187 | ```
|
188 |
|
189 | ## Changelog
|
190 |
|
191 | ### [2.1.4] - 2019-02-15
|
192 |
|
193 | - Initial isLoading state will now check the data object's isDataLoading()
|
194 |
|
195 | ### [2.1.1] - 2019-01-31
|
196 |
|
197 | #### Changed
|
198 |
|
199 | - [FIXED] Missing property "type" on the supplied filter element!
|
200 |
|
201 | ### [2.1.0] - 2019-01-31
|
202 |
|
203 | #### Changed
|
204 |
|
205 | - The filter argument passed to the useFetchRecord and useFetchData can now be a filter object
|
206 |
|
207 | #### Added
|
208 |
|
209 | - connectRow alias to connect to a row without second parameter.
|
210 | - getData - the function used by useFetchRecord and useFetchData is now exported
|
211 |
|
212 | #### Deprecated
|
213 |
|
214 | - dataObjectConnect has been renamed to connect
|
215 | - useSingleRow has been renamed to useFetchRecord
|
216 | - useDataWithoutState has been renamed to useFetchData
|
217 |
|
218 | ### [2.0.1] - 2019-01-30
|
219 |
|
220 | #### Added
|
221 |
|
222 | - Added useDataWithoutState hook
|
223 |
|
224 | #### Breaking changes
|
225 |
|
226 | - Hooks are now top level exports instead of children of dataObjectHooks
|
227 |
|
228 | ### [1.1.0] - 2019-01-28
|
229 |
|
230 | #### Added
|
231 |
|
232 | - Added useSingleRow hook
|
233 |
|
234 | [2.1.4]: https://github.com/olenbetong/react-data-object-connect/compare/v2.1.1...v2.1.4
|
235 | [2.1.1]: https://github.com/olenbetong/react-data-object-connect/compare/v2.1.0...v2.1.1
|
236 | [2.1.0]: https://github.com/olenbetong/react-data-object-connect/compare/v2.0.0...v2.1.0
|
237 | [2.0.1]: https://github.com/olenbetong/react-data-object-connect/compare/v1.1.0...v2.0.1
|
238 | [1.1.0]: https://github.com/olenbetong/react-data-object-connect/compare/v1.0.1...v1.1.0
|