Skip to content

Commit

Permalink
Merge pull request #18 from razorcreations/release/1.2.0
Browse files Browse the repository at this point in the history
Release/1.2.0
  • Loading branch information
Stowez authored Nov 5, 2024
2 parents de8e78d + 96b41ca commit a5a3921
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 42 deletions.
6 changes: 6 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## 1.2.0 - 2024-11-05

- Fixed javascript error when inside a flexible componet
- Any Ajax Request results are now stored in a cached variable so label isn't lost on search
- Use Nova Placeholder before name on search input

## 1.0.1 - 2022-05-11

- Added filterable option flag, contributed by https://github.com/nea
Expand Down
10 changes: 2 additions & 8 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "razorcreations/ajax-field",
"description": "A searchable AJAX powered field for Laravel Nova.",
"version": "1.2.0",
"authors": [
{
"name": "Ross Cooper",
Expand All @@ -24,8 +25,7 @@
],
"license": "MIT",
"require": {
"php": "^7.3|^8.0",
"laravel/nova": "^4.0"
"php": "^7.3|^8.0"
},
"autoload": {
"psr-4": {
Expand All @@ -44,12 +44,6 @@
},
"minimum-stability": "dev",
"prefer-stable": true,
"repositories": {
"nova": {
"type": "composer",
"url": "https://nova.laravel.com"
}
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.8"
},
Expand Down
2 changes: 1 addition & 1 deletion dist/js/field.js

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions dist/js/field.js.LICENSE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@
* @license MIT
*/

/**
* @license
* Lodash <https://lodash.com/>
* Copyright JS Foundation and other contributors <https://js.foundation/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/

/**
* @license
* Lodash <https://lodash.com/>
Expand Down
3 changes: 3 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ For Nova 3 support use
## Usage

```php

use Razorcreations\AjaxField\AjaxField;

// Inside your resources fields definition
AjaxField::make('Foo')->setUrl('/api/ajaxselect/foo'),

Expand Down
86 changes: 54 additions & 32 deletions resources/js/components/FormField.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
v-model="value"
class="w-full form-control form-input form-input-bordered"
:class="errorClasses"
:placeholder="field.name"
:placeholder="field.placeholder || field.name"
:options="availableOptions"
:label="labelKey"
:multiple="field.multiple"
Expand All @@ -30,16 +30,16 @@ import _ from 'lodash';
import { isArray } from 'util';
export default {
components: {
VueSelect,
},
mixins: [FormField, HandlesValidationErrors],
props: ['resourceName', 'resourceId', 'field'],
data () {
data() {
return {
optionsCache: [],
options: [],
loading: false,
labelKey: 'label',
Expand All @@ -52,16 +52,20 @@ export default {
computed: {
parentComponent() {
if(!this.field.parent_field) {
if (!this.field.parent_field) {
return false;
}
let targetField = this.field.parent_field;
let currentField = this.field.attribute;
let currentField = this.field.attribute;
// If component is inside a flexible, key is prefixed with an id
if( currentField.indexOf('__') ) {
targetField = currentField.substr(0, currentField.indexOf('__')) + '__' + targetField;
if (currentField.indexOf('__')) {
targetField = currentField.substr(0, currentField.indexOf('__')) + '__' + targetField;
}
if (typeof this.$parent.$children === 'undefined') {
return;
}
// Find the component the parent value references
Expand All @@ -71,14 +75,14 @@ export default {
})
},
availableOptions () {
return _.uniq(this.options.concat(this.selectedOptions), 'value');
availableOptions() {
return _.uniqBy(this.options.concat(this.selectedOptions), 'value');
},
},
mounted () {
mounted() {
this.parseInitialValue();
if(this.parentComponent) {
if (this.parentComponent) {
this.parentComponent.$watch('value', (value) => {
this.parentVal = value;
this.prepareField();
Expand All @@ -91,17 +95,17 @@ export default {
methods: {
prepareField() {
//Check whether any filterable data was set, otherwise stay true
if(this.field.filterable !== 'undefined') {
if (typeof this.field.filterable !== 'undefined') {
this.filterable = this.field.filterable;
}
// If field is not responsive, load initial options
if(!this.field.responsive) {
if (!this.field.responsive) {
return this.loadInitialOptions();
}
// If field is responsive, do we have any initial values
if(this.field.value ) {
if (this.field.value) {
return this.loadInitialOptions(this.field.value);
}
},
Expand All @@ -122,17 +126,18 @@ export default {
/*
* Load initial Options
*/
loadInitialOptions (value) {
*/
loadInitialOptions(value) {
let url = this.buildParamString(null, value);
if(Array.isArray(value) && value.length === 1 && !value[0]) {
if (Array.isArray(value) && value.length === 1 && !value[0]) {
this.value = [];
return;
}
window.Nova.request().get( url ).then(({data}) => {
window.Nova.request().get(url).then(({ data }) => {
this.options = data;
this.cacheOptions(data);
this.options.forEach(option => {
if (isArray(this.value)) {
Expand All @@ -147,26 +152,39 @@ export default {
this.selectedOptions.push(option);
}
})
}).catch(error => {
console.error('Error loading initial options:', error);
});
},
/*
* Dynamic search with the input value
*/
*/
search: window._.debounce((loading, searchVal, vm) => {
let url = vm.buildParamString(searchVal)
window.Nova.request().get( url ).then(({data}) => {
window.Nova.request().get(url).then(({ data }) => {
vm.options = data;
vm.cacheOptions(data);
loading(false);
});
}, 350),
/*
* Cache options to optionsCache
*/
cacheOptions(options) {
options.forEach(option => {
if (!this.optionsCache.find(o => o.value === option.value)) {
this.optionsCache.push(option);
}
});
},
/*
* When multiselect input changes, determine if ready to query
*/
inputChange (input, loading) {
if( input.length < 3 && !/^\d+$/.test(input)) {
inputChange(input, loading) {
if (input.length < 3 && !/^\d+$/.test(input)) {
return;
}
loading(true);
Expand All @@ -183,15 +201,15 @@ export default {
let params = {}
let url = this.field.url;
if(this.parentVal) {
if (this.parentVal) {
params[this.field.parent_field] = this.parentVal;
}
if(this.field.responsive && searchVal) {
if (this.field.responsive && searchVal) {
params.search = searchVal
}
if(fieldVal) {
if (fieldVal) {
params.value = fieldVal
}
Expand All @@ -200,7 +218,7 @@ export default {
return url = url + '?' + paramString;
},
parseInitialValue () {
parseInitialValue() {
let value = this.field.value ? this.field.value : null;
if (!value) {
this.value = value;
Expand Down Expand Up @@ -237,12 +255,16 @@ export default {
if (!v) {
return;
}
const selectedOption = this.options.find(option => option.value === v);
this.selectedOptions.push(selectedOption);
const selectedOption = this.optionsCache.find(option => option.value === v);
if (selectedOption) {
this.selectedOptions.push(selectedOption);
}
});
} else {
const selectedOption = this.options.find(option => option.value === value);
this.selectedOptions.push(selectedOption);
const selectedOption = this.optionsCache.find(option => option.value === value);
if (selectedOption) {
this.selectedOptions.push(selectedOption);
}
}
}
},
Expand All @@ -257,4 +279,4 @@ export default {
.vs__dropdown-toggle {
border-color: transparent !important;
}
</style>
</style>
2 changes: 1 addition & 1 deletion version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.1.0
1.2.0

0 comments on commit a5a3921

Please sign in to comment.