framework7io / framework7

Full featured HTML framework for building iOS & Android apps
http://framework7.io
MIT License
18.14k stars 3.23k forks source link

Autocomplete shows id in input instead of value after select #3844

Closed juanreynolds closed 3 years ago

juanreynolds commented 3 years ago

Describe the bug

When autocomplete data is an object the selected object's id instead of text is displayed in the input. According to documentation the text property must display in the input.

To Reproduce

Autocomplete filters on data that is an object with id and text properties:

const fruits = [
            {
                id: '0',
                text: 'Apple'
            },
        ...
        ];

Do a search for 'Apple' in the autocomplete input. The dropdown correctly show the search result of 'Apple'. Click on 'Apple'. The autocomplete now show the id of '0' in the input instead of the 'text' of 'Apple'.

Expected behavior

When you click on the search result the selected item must display its text property in the input.

Actual Behavior

When you click on the search result the selected item displays its id property in the input.

Error in code (autocomplete-class.js, line 301:

- ac.$inputEl.val(typeof clickedItem === 'object' ? clickedItem[ac.params.valueProperty] : clickedItem);
+ ac.$inputEl.val(typeof clickedItem === 'object' ? clickedItem[ac.params.textProperty] : clickedItem);
nolimits4web commented 3 years ago

Check documentation, it is configurable in Autcomplete parameters https://framework7.io/docs/autocomplete.html

juanreynolds commented 3 years ago

The default is as follows:

valueProperty string id Name of matched item object's key that represents item value
textProperty string text Name of matched item object's key that represents item display value which is used as title of displayed options

Even if I put my own properties it does not work. I can switch id and text properties, then when you search it displays the id (wrong) and when you select it displays the text (correct). It is mismatched.

Look at this line here from code: ac.$inputEl.val(typeof clickedItem === 'object' ? clickedItem[ac.params.valueProperty] : clickedItem); It is trying to show valueProperty as the value for $inputEl. It must show the textProperty.

nolimits4web commented 3 years ago

It is trying to show valueProperty as the value for $inputEl

Everything is correct here. input must have a value and it displays valueProperty. Text input can't have one value and display something different

juanreynolds commented 3 years ago

I'm trying to create a Fiddle so you can see, but I am unable to. Can I please post my code and a few screenshots to show you.

const FormAutocomplete: React.FC = ({ attrs, error, value, onBlur, onChange }) => {

    const $ = f7.$;

    useEffect(() => {        

        const fruits = [
            {
                id: '0',
                text: 'Apple'
            },
            {
                id: '1',
                text: 'Apricot'
            },
            {
                id: '2',
                text: 'Avocado'
            },
            {
                id: '3',
                text: 'Banana'
            },
            {
                id: '4',
                text: 'Melon'
            },
            {
                id: '5',
                text: 'Orange'
            },
            {
                id: '6',
                text: 'Peach'
            },
            {
                id: '7',
                text: 'Pear'
            },
            {
                id: '8',
                text: 'Pineapple'
            }
        ];

        const autoComplete = f7.autocomplete.create({
            inputEl: '#autocomplete-dropdown',
            openIn: 'dropdown',  
            textProperty: 'text',
            valueProperty: 'id',
            source(query, render) {

                const results: any[] = [];
                if (query.length === 0) {
                    render(results);
                    return;
                }
                // Find matched items
                for (let i = 0; i < fruits.length; i += 1) {
                    if (fruits[i].text.toLowerCase().indexOf(query.toLowerCase()) >= 0) results.push(fruits[i]);
                }
                // Render items by passing array with result items
                render(results);

            },
        }); 
        return () => autoComplete.destroy();
    }, []);

    return (
        <ListInput
            label="Fruit"
            inlineLabel
            type="text"
            placeholder="Fruit"
            inputId="autocomplete-dropdown"
        />
    );
}

When I search Banana this is shown Screenshot from 2021-03-23 15-10-30

When I click on Banana this is show:

Screenshot from 2021-03-23 15-10-34

If I then configure parameters differently like this:

            textProperty: 'id',
            valueProperty: 'text',

Then when I search it is like this:

Screenshot from 2021-03-23 15-15-41

And when I click on 3 (the id that is returned instaed of the workd banana) I get this:

Screenshot from 2021-03-23 15-15-47

nolimits4web commented 3 years ago

textProperty is what displayed in autocomplete. valueProperty is what will be inserted to input. Everything is correct according to your code and screenshot. If you want to display banana everywhere you need to put text in both properties

juanreynolds commented 3 years ago

Thanks for your time and patience. I think I get it now, I can change the data like this:

{ id: string, text: string, value: string }

or set properties like this: textProperty: 'text', valueProperty: 'text',