mirror of
https://github.com/silverstripe/silverstripe-tagfield
synced 2024-10-22 11:05:32 +02:00
Setup TagField to work within AssetAdmin (Fixes #107)
This commit is contained in:
parent
bc7404005b
commit
068e4c6a26
5
_config/admin.yml
Normal file
5
_config/admin.yml
Normal file
@ -0,0 +1,5 @@
|
||||
SilverStripe\Admin\LeftAndMain:
|
||||
extra_requirements_css:
|
||||
- 'silverstripe/tagfield:client/dist/styles/bundle.css'
|
||||
extra_requirements_javascript:
|
||||
- 'silverstripe/tagfield:client/dist/js/bundle.js'
|
@ -1,6 +1,7 @@
|
||||
import React, { Component } from 'react';
|
||||
import Select from 'react-select';
|
||||
import fetch from 'isomorphic-fetch';
|
||||
import fieldHolder from 'components/FieldHolder/FieldHolder';
|
||||
import url from 'url';
|
||||
import debounce from 'debounce-promise';
|
||||
import PropTypes from 'prop-types';
|
||||
@ -15,6 +16,7 @@ class TagField extends Component {
|
||||
};
|
||||
|
||||
this.onChange = this.onChange.bind(this);
|
||||
this.handleOnBlur = this.handleOnBlur.bind(this);
|
||||
this.getOptions = this.getOptions.bind(this);
|
||||
this.fetchOptions = debounce(this.fetchOptions, 500);
|
||||
}
|
||||
@ -43,6 +45,15 @@ class TagField extends Component {
|
||||
return this.fetchOptions(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Required to prevent TagField being cleared on blur
|
||||
*
|
||||
* @link https://github.com/JedWatson/react-select/issues/805
|
||||
*/
|
||||
handleOnBlur() {
|
||||
|
||||
}
|
||||
|
||||
fetchOptions(input) {
|
||||
const { optionUrl, labelKey, valueKey } = this.props;
|
||||
const fetchURL = url.parse(optionUrl, true);
|
||||
@ -52,8 +63,8 @@ class TagField extends Component {
|
||||
.then((response) => response.json())
|
||||
.then((json) => ({
|
||||
options: json.items.map(item => ({
|
||||
[labelKey]: item.id,
|
||||
[valueKey]: item.text,
|
||||
[labelKey]: item.Title,
|
||||
[valueKey]: item.Value,
|
||||
}))
|
||||
}));
|
||||
}
|
||||
@ -85,6 +96,7 @@ class TagField extends Component {
|
||||
<SelectComponent
|
||||
{...passThroughAttributes}
|
||||
onChange={this.onChange}
|
||||
onBlur={this.handleOnBlur}
|
||||
inputProps={{ className: 'no-change-track' }}
|
||||
{...optionAttributes}
|
||||
/>
|
||||
@ -113,4 +125,6 @@ TagField.defaultProps = {
|
||||
disabled: false
|
||||
};
|
||||
|
||||
export default TagField;
|
||||
export { TagField as Component };
|
||||
|
||||
export default fieldHolder(TagField);
|
||||
|
116
src/TagField.php
116
src/TagField.php
@ -6,15 +6,13 @@ use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Control\HTTPRequest;
|
||||
use SilverStripe\Control\HTTPResponse;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Forms\DropdownField;
|
||||
use SilverStripe\Forms\MultiSelectField;
|
||||
use SilverStripe\Forms\Validator;
|
||||
use SilverStripe\ORM\ArrayList;
|
||||
use SilverStripe\ORM\DataList;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\DataObjectInterface;
|
||||
use SilverStripe\ORM\SS_List;
|
||||
use SilverStripe\View\ArrayData;
|
||||
use SilverStripe\View\Requirements;
|
||||
|
||||
/**
|
||||
* Provides a tagging interface, storing links between tag DataObjects and a parent DataObject.
|
||||
@ -22,7 +20,7 @@ use SilverStripe\View\Requirements;
|
||||
* @package forms
|
||||
* @subpackage fields
|
||||
*/
|
||||
class TagField extends DropdownField
|
||||
class TagField extends MultiSelectField
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
@ -61,6 +59,9 @@ class TagField extends DropdownField
|
||||
*/
|
||||
protected $isMultiple = true;
|
||||
|
||||
/** @skipUpgrade */
|
||||
protected $schemaComponent = 'TagField';
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string $title
|
||||
@ -236,19 +237,6 @@ class TagField extends DropdownField
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* When not used in a React form factory context, this adds the schema data to SilverStripe template
|
||||
* rendered attributes lists
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAttributes()
|
||||
{
|
||||
$attributes = parent::getAttributes();
|
||||
$attributes['data-schema'] = json_encode($this->getSchemaData());
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
@ -258,11 +246,12 @@ class TagField extends DropdownField
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $onlySelected Only return options that are selected
|
||||
* @return ArrayList
|
||||
*/
|
||||
protected function getOptions($onlySelected = false)
|
||||
protected function getOptions()
|
||||
{
|
||||
$options = ArrayList::create();
|
||||
|
||||
$source = $this->getSourceList();
|
||||
|
||||
if (!$source) {
|
||||
@ -270,35 +259,28 @@ class TagField extends DropdownField
|
||||
}
|
||||
|
||||
$dataClass = $source->dataClass();
|
||||
$titleField = $this->getTitleField();
|
||||
|
||||
$values = $this->Value();
|
||||
|
||||
if ($values) {
|
||||
if (is_array($values)) {
|
||||
$values = $source->filter($titleField, $values);
|
||||
}
|
||||
}
|
||||
if ($onlySelected) {
|
||||
$source = $values;
|
||||
if (!$values) {
|
||||
return $options;
|
||||
}
|
||||
|
||||
return $source instanceof DataList ? $this->formatOptions($source) : ArrayList::create();
|
||||
}
|
||||
if (is_array($values)) {
|
||||
$values = DataList::create($dataClass)
|
||||
->filter($this->getTitleField(), $values);
|
||||
}
|
||||
|
||||
$ids = $values->column($this->getTitleField());
|
||||
|
||||
/**
|
||||
* @param DataList $source
|
||||
* @return ArrayList
|
||||
*/
|
||||
protected function formatOptions(DataList $source)
|
||||
{
|
||||
$options = ArrayList::create();
|
||||
$titleField = $this->getTitleField();
|
||||
|
||||
foreach ($source as $object) {
|
||||
$options->push(
|
||||
ArrayData::create([
|
||||
'Title' => $object->$titleField,
|
||||
'Value' => $object->Title,
|
||||
'Value' => $object->ID,
|
||||
'Selected' => in_array($object->$titleField, $ids),
|
||||
])
|
||||
);
|
||||
}
|
||||
@ -315,17 +297,41 @@ class TagField extends DropdownField
|
||||
$name = $this->getName();
|
||||
|
||||
if ($source->hasMethod($name)) {
|
||||
$value = $source->$name()->column($this->getTitleField());
|
||||
$values = [];
|
||||
$titleField = $this->getTitleField();
|
||||
|
||||
foreach ($source->$name() as $tag) {
|
||||
$values[] = [
|
||||
'Title' => $tag->$titleField,
|
||||
'Value' => $tag->ID,
|
||||
'Selected' => true
|
||||
];
|
||||
}
|
||||
|
||||
return parent::setValue($values);
|
||||
}
|
||||
} elseif ($value instanceof SS_List) {
|
||||
$value = $value->column($this->getTitleField());
|
||||
}
|
||||
|
||||
if (!is_array($value)) {
|
||||
return parent::setValue($value);
|
||||
}
|
||||
|
||||
return parent::setValue(array_filter($value));
|
||||
return parent::setValue($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAttributes()
|
||||
{
|
||||
return array_merge(
|
||||
parent::getAttributes(),
|
||||
[
|
||||
'name' => $this->getName() . '[]',
|
||||
'style' => 'width: 100%',
|
||||
'data-schema' => json_encode($this->getSchemaData()),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -333,8 +339,6 @@ class TagField extends DropdownField
|
||||
*/
|
||||
public function saveInto(DataObjectInterface $record)
|
||||
{
|
||||
parent::saveInto($record);
|
||||
|
||||
$name = $this->getName();
|
||||
$titleField = $this->getTitleField();
|
||||
$values = $this->Value();
|
||||
@ -344,6 +348,7 @@ class TagField extends DropdownField
|
||||
if (!$values) {
|
||||
$values = [];
|
||||
}
|
||||
|
||||
if (empty($record) || empty($titleField)) {
|
||||
return;
|
||||
}
|
||||
@ -388,6 +393,11 @@ class TagField extends DropdownField
|
||||
if ($this->getCanCreate()) {
|
||||
$dataClass = $source->dataClass();
|
||||
$record = Injector::inst()->create($dataClass);
|
||||
|
||||
if (is_array($term)) {
|
||||
$term = $term['Value'];
|
||||
}
|
||||
|
||||
$record->{$titleField} = $term;
|
||||
$record->write();
|
||||
if ($source instanceof SS_List) {
|
||||
@ -438,8 +448,8 @@ class TagField extends DropdownField
|
||||
$titleField = $this->getTitleField();
|
||||
foreach ($query->map('ID', $titleField) as $id => $title) {
|
||||
$items[$title] = [
|
||||
'id' => $title,
|
||||
'text' => $title,
|
||||
'Title' => $title,
|
||||
'Value' => $id,
|
||||
];
|
||||
}
|
||||
|
||||
@ -480,4 +490,20 @@ class TagField extends DropdownField
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function getSchemaStateDefaults()
|
||||
{
|
||||
$data = parent::getSchemaStateDefaults();
|
||||
|
||||
// Add options to 'data'
|
||||
$data['lazyLoad'] = $this->getShouldLazyLoad();
|
||||
$data['multi'] = $this->getIsMultiple();
|
||||
$data['optionUrl'] = $this->getSuggestURL();
|
||||
$data['creatable'] = $this->getCanCreate();
|
||||
$data['value'] = $this->Value();
|
||||
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user