Skip to content

Commit

Permalink
fix field saving issue
Browse files Browse the repository at this point in the history
  • Loading branch information
iamntz committed Feb 25, 2020
1 parent bf5f391 commit 9794cab
Show file tree
Hide file tree
Showing 10 changed files with 576 additions and 489 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ node_modules
coverage

/vendor/

/.idea/
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
# Carbon Field: rest_multiselect
# Carbon Field: `rest_multiselect`

carbon rest multiselect
Prov

Adds a `rest_multiselect` field type to Carbon Fields 3. Install using Composer:

```cli
composer require iamntz/carbon-rest-multiselect:v3.x-dev
composer require iamntz/carbon-rest-multiselect:^3.0
```

For Carbon Fields 2 (legacy):

```cli
composer require iamntz/carbon-rest-multiselect:^2.0"
```

Usage:
Expand All @@ -22,6 +28,7 @@ Field::make('rest_multiselect', 'my-name', 'My Label')
```

**ALL** endpoints are required!
If needed, you can specify nonces (or extra variables) directly on the endpoint url: `get_rest_url( null, "wp/v2/posts/?nonce={$generated_nonce}&search=" )`

#### `set_label_key`

Expand All @@ -35,7 +42,7 @@ You can also set some transformations on labels:

Basically any JS prototype function that's callable on a string.

There is an exception: you can use a `wrap` transform that will ... well, wrapp your label.
There is an exception: you can use a `wrap` transform that will ... well, wrap your label.

#### `set_selection_limit`
You can set what's the maximum amount of selectable items. This will work ad infinitum, without any limit or warning (just like regular HTML `select` tag works). So any new selection will be appended to the existing items, therefore if the limit is reached, then the first element of the selection is lost, the new element will be appended.
Expand All @@ -50,7 +57,7 @@ The field will _always_ return an array of items, with values picked form the ke


### Support me
You can get [hosting](https://m.do.co/c/c95a44d0e992), [donate](https://www.paypal.me/iamntz) or buy me a [gift](http://iamntz.com/wishlist).
You can get [hosting](https://m.do.co/c/c95a44d0e992), [donate](https://www.paypal.me/iamntz) or be my [patreon](https://www.patreon.com/iamntz).

### License

Expand Down
105 changes: 36 additions & 69 deletions assets/build/bundle.js

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions assets/build/bundle.min.js

Large diffs are not rendered by default.

185 changes: 185 additions & 0 deletions assets/src/Field.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
/**
* External dependencies.
*/
import { Component } from '@wordpress/element';
import { isArray } from 'lodash';
import he from 'he';

import Async from 'react-select/async';

import labelTransforms from './inc/transforms';

import resolve from './inc/resolve';

class Field extends Component {
state = {
optionsLoaded: false,
selectedValues: [],
};

fetchDebounce = null;
abortFetchSignal = null;

constructor(props) {
super(props);
}

componentDidMount() {
this.prepareSelectedValue();
}

fetch(endpoint, callback) {
try {
window.clearTimeout(this.fetchDebounce);
} catch (e) {
}

this.fetchDebounce = window.setTimeout(() => {
this._fetch(endpoint, callback);
}, 100);
}

_fetch(endpoint, callback, withAbort = true) {
const { field } = this.props;

const parseData = (data) => {
let label;

if (isArray(field.label_key)) {
label = field.label_key
.map((piece) => labelTransforms(piece, data))
.join(' ');
} else {
label = labelTransforms(field.label_key, data);
}

return {
value: resolve(field.value_key, data),
label: he.decode(label),
};
};

let signal = null;

if (withAbort) {
try {
this.abortFetchSignal.abort();
} catch (e) {
}
this.abortFetchSignal = new AbortController();
signal = this.abortFetchSignal.signal;
}


return fetch(endpoint, {
signal,
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
})
.then(response => {
if (response.ok) {
return response;
}

throw new Error(`Network response was not ok. Status: ${response.status} ${response.statusText}`);
})
.then((r) => r.json())
.then((data) => {
console.log(data.map(parseData));
return callback(data.map(parseData));
})
.catch((error) => {
console.warn('Something went wrong on fetching. Are you sure you set the correct endpoints?');
console.error(error);
});
}

loadOptions(query, callback) {
this.fetch(this.props.field.search_endpoint + query, callback);
}

limitResults(results) {
const { selection_limit } = this.props.field;

if (results && results.length && selection_limit > 0) {
results = results.slice(results.length - selection_limit);
}

return results;
}

handleOnChange(selectedValues) {
const { id, onChange } = this.props;

let value = this.limitResults(selectedValues);

this.setState({
...this.state,
selectedValues: value,
});

value = !value ? null : value.map(selectedValue => selectedValue.value);

onChange(id, value);
}

prepareSelectedValue() {
const { value, field } = this.props;

if (this.state.optionsLoaded) {
return;
}

console.log('====================================');
console.log('====================================');
console.log(value);
console.log('====================================');
console.log('====================================');
if (!value.length) {
this.setState({
...this.state,
optionsLoaded: true,
});

return;
}

const endpoint = field.fetch_by_id_endpoint + value.join(',');

this._fetch(endpoint, (data) => {
this.setState({
...this.state,
selectedValues: data,
optionsLoaded: true,
});
}, false);
}

render() {
const { field, name } = this.props;

return (
<Async
name={`${name}[]`}
closeMenuOnSelect={false}
isDisabled={!this.props.visible || !this.state.optionsLoaded}

onChange={this.handleOnChange.bind(this)}
loadOptions={(query, callback) => this.loadOptions(query, callback)}

value={this.state.selectedValues}

delimiter={field.valueDelimiter}
cacheOptions
defaultOptions
isMulti
/>
);
}
}


export default Field;
138 changes: 0 additions & 138 deletions assets/src/field.js

This file was deleted.

2 changes: 1 addition & 1 deletion assets/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
import { registerFieldType } from '@carbon-fields/core';
import './style.scss';

import Field from './field';
import Field from './Field';

registerFieldType('rest_multiselect', Field);
Loading

0 comments on commit 9794cab

Please sign in to comment.