Skip to content

Commit

Permalink
FIX Selected tag is not shown when isMutliple is false (#201)
Browse files Browse the repository at this point in the history
* doc: add note about `setTitleField` (Fixes #153)

* NEW Add support for saving tag value into has_one components

FIX Value not shown if isMultiple is false (#195)

* fix: don't default to ID column as pgsql throws an error if comparing string value
  • Loading branch information
wilr committed Jun 7, 2022
1 parent ee7c422 commit 527c5b2
Show file tree
Hide file tree
Showing 11 changed files with 300 additions and 124 deletions.
1 change: 1 addition & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ trim_trailing_whitespace = true
[{*.yml,package.json,*.js,*.scss}]
indent_size = 2
indent_style = space
quote_type = single

# The indent size used in the package.json file cannot be changed:
# https://github.com/npm/npm/pull/3180#issuecomment-16336516
2 changes: 1 addition & 1 deletion client/dist/js/bundle.js

Large diffs are not rendered by default.

33 changes: 21 additions & 12 deletions client/src/components/TagField.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class TagField extends Component {
}

this.setState({
value
value,
});
}

Expand All @@ -76,9 +76,7 @@ class TagField extends Component {
*
* @link https://github.com/JedWatson/react-select/issues/805
*/
handleOnBlur() {

}
handleOnBlur() {}

/**
* Initiate a request to fetch options, optionally using the given string as a filter.
Expand All @@ -94,20 +92,17 @@ class TagField extends Component {
return fetch(url.format(fetchURL), { credentials: 'same-origin' })
.then((response) => response.json())
.then((json) => ({
options: json.items.map(item => ({
options: json.items.map((item) => ({
[labelKey]: item.Title,
[valueKey]: item.Value,
}))
Selected: item.Selected,
})),
}));
}

render() {
const {
lazyLoad,
options,
creatable,
...passThroughAttributes
} = this.props;
const { lazyLoad, options, creatable, ...passThroughAttributes } =
this.props;

const optionAttributes = lazyLoad
? { loadOptions: this.getOptions }
Expand All @@ -128,6 +123,20 @@ class TagField extends Component {
passThroughAttributes.value = this.state.value;
}

// if this is a single select then we just need the first value
if (!passThroughAttributes.multi && passThroughAttributes.value) {
if (Object.keys(passThroughAttributes.value).length > 0) {
const value =
passThroughAttributes.value[
Object.keys(passThroughAttributes.value)[0]
];

if (typeof value === 'object') {
passThroughAttributes.value = value;
}
}
}

return (
<SelectComponent
{...passThroughAttributes}
Expand Down
14 changes: 14 additions & 0 deletions docs/en/using.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,17 @@ class BlogPost extends DataObject
In the above code example, the options available (whether lazy loaded or not) would be "one" and "two", and the
user would be able to create new options. Whichever tags are chosen would be stored in the BlogPost's `Tags` field
as a comma-delimited string.

## Using TagField with silverstripe-taxonomy

TagField assumes a `Title` field on objects. For classes without a `Title` field
use `setTitleField` to modify accordingly.

```php
$field = TagField::create(
'Tags',
'Blog Tags',
TaxonomyTerm::get(),
)
->setTitleField('Name');
```
73 changes: 48 additions & 25 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ use SilverStripe\ORM\DataObject;

class BlogPost extends DataObject
{
private static $many_many = [
'BlogTags' => BlogTag::class
];
private static $many_many = [
'BlogTags' => BlogTag::class
];
}
```

Expand All @@ -50,27 +50,28 @@ use SilverStripe\ORM\DataObject;

class BlogTag extends DataObject
{
private static $db = [
'Title' => 'Varchar(200)',
];
private static $db = [
'Title' => 'Varchar(200)',
];

private static $belongs_many_many = [
'BlogPosts' => BlogPost::class
];
private static $belongs_many_many = [
'BlogPosts' => BlogPost::class
];
}
```

```php
$field = TagField::create(
'BlogTags',
'Blog Tags',
BlogTag::get(),
$this->BlogTags()
'BlogTags',
'Blog Tags',
BlogTag::get(),
$this->BlogTags()
)
->setShouldLazyLoad(true) // tags should be lazy loaded
->setCanCreate(true); // new tag DataObjects can be created
->setShouldLazyLoad(true) // tags should be lazy loaded
->setCanCreate(true); // new tag DataObjects can be created
```
**Note:** This assumes you have imported the namespaces class, e.g. use SilverStripe\TagField\TagField;
**Note:** This assumes you have imported the namespaces class, e.g. use
SilverStripe\TagField\TagField;

### String Tags

Expand All @@ -79,31 +80,53 @@ use SilverStripe\ORM\DataObject;

class BlogPost extends DataObject
{
private static $db = [
'Tags' => 'Text',
];
private static $db = [
'Tags' => 'Text',
];
}
```

```php
$field = StringTagField::create(
'Tags',
'Tags',
'Tags',
'Tags',
['one', 'two'],
explode(',', $this->Tags)
explode(',', $this->Tags)
);

$field->setShouldLazyLoad(true); // tags should be lazy loaded
```

You can find more in-depth documentation in [docs/en](docs/en/introduction.md).

## Using TagField with silverstripe-taxonomy

TagField assumes a `Title` field on objects. For classes without a `Title` field
use `setTitleField` to modify accordingly.

```php
$field = TagField::create(
'Tags',
'Blog Tags',
TaxonomyTerm::get(),
)
->setTitleField('Name');
```

## Versioning

This library follows [Semver](http://semver.org). According to Semver, you will be able to upgrade to any minor or patch version of this library without any breaking changes to the public API. Semver also requires that we clearly define the public API for this library.
This library follows [Semver](http://semver.org). According to Semver, you will
be able to upgrade to any minor or patch version of this library without any
breaking changes to the public API. Semver also requires that we clearly define
the public API for this library.

All methods, with `public` visibility, are part of the public API. All other methods are not part of the public API. Where possible, we'll try to keep `protected` methods backwards-compatible in minor/patch versions, but if you're overriding methods then please test your work before upgrading.
All methods, with `public` visibility, are part of the public API. All other
methods are not part of the public API. Where possible, we'll try to keep
`protected` methods backwards-compatible in minor/patch versions, but if you're
overriding methods then please test your work before upgrading.

## Reporting Issues

Please [create an issue](http://github.com/silverstripe/silverstripe-tagfield/issues) for any bugs you've found, or features you're missing.
Please [create an
issue](http://github.com/silverstripe/silverstripe-tagfield/issues) for any bugs
you've found, or features you're missing.
43 changes: 43 additions & 0 deletions src/StringTagField.php
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,49 @@ public function suggest(HTTPRequest $request)
return $response;
}

/**
* Get or create tag with the given value
*
* @param string $term
* @return DataObject|bool
*/
protected function getOrCreateTag($term)
{
// Check if existing record can be found
$source = $this->getSourceList();
if (!$source) {
return false;
}

$titleField = $this->getTitleField();
$record = $source
->filter($titleField, $term)
->first();
if ($record) {
return $record;
}

// Create new instance if not yet saved
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) {
$source->add($record);
}
return $record;
}

return false;
}


/**
* Returns array of arrays representing tags that partially match the given search term
*
Expand Down
Loading

0 comments on commit 527c5b2

Please sign in to comment.