Shane
Shane

Reputation: 23

Give a value from a Json file to a select

I want to give to my suggestor a value from a Json file. The name of those value are displayed in my select but when I am returning with an alert() my value it shows 'null'. I want to use as a value the name already displayed/visible in the select.

The purpose of my application is after somebody choose a name in the select to show all the data from both database that has the same name.

This is the structure of both JSON file they all have different id, name,admin_area & country value

  {
    "id": 3,
    "name": "Satimola",
    "admin_area": "Theo",
    "country": "Taiwan"
  }

Of course I tried to pass my array suggestionOldData as a value but it didn't work the console said :

Failed prop type: Invalid prop value of type array supplied to Suggestor, expected string.

import React from "react";
import { Component } from "react";
import ReactDOM from "react-dom";
// IMPORT DATA FROM  JSON FILE
import NewData from "../../api/data/cities.json";
import OldData from "../../api/data/historical.json";
// IMPORT PAGINATION FILE
import Pagination from "./Pagination.js";
// IMPORT MODULE TO CREATE INPUT SEARCH
import Suggestor from "ssuggestor";

// CREATE A COMPONENT THAT WILL SHOW THE NEW DATA IN A TABLE
class NewDataTable extends React.Component {
  constructor() {
    super();

    this.state = {
      NewData: NewData,
      pageOfItems: []
    };

    this.onChangePage = this.onChangePage.bind(this);
    this.handleChange = this.handleChange.bind(this);
  }

  onChangePage(pageOfItems) {
    // update state with new page of items
    this.setState({ pageOfItems: pageOfItems });
  }

  // GET INPUT VALUE , GET DATA WITH THE SAME NAME IN BOTH ARRAY, CONSOLE.LOG BOTH
  handleChange(event) {
    var val = document.getElementById(Suggestor);
    alert(val);
    const consoleOldData = OldData.find(value => value.name);
    const consoleNewData = NewData.find(value => value.name);
    console.log("Old Data =>", consoleOldData);
    console.log("New Data =>", consoleNewData);
  }

  render() {
    // GET DATA.NAME FROM OldData
    const suggesttionOldData = OldData.map(value => value.name);

    return (
      <div>
        <form>
          <Suggestor
            id="Suggestor"
            list={suggesttionOldData}
            onSelect={this.handleChange}
            placeholder="  ..."
            value={this.state.value}
          />
        </form>

        <nav>
          <Pagination
            items={this.state.NewData}
            onChangePage={this.onChangePage}
          />
        </nav>
        <table>
          <tbody>
            <tr>
              <th>New Data</th>
            </tr>

            {this.state.pageOfItems.map(item => (
              <tr key={item.id}>
                <td key={item.id}>{item.name}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    );
  }
}

export default NewDataTable;

This is the suggestor class





class Suggestor extends PureComponent {
    constructor(props) {
        super(props);
        autoBind(this);

        this.input = React.createRef();

        this.state = {
            filtered: this.filter(props.list, props.value, false),
            value: props.value,
            open: false,
            index: 0
        };
    }
    componentDidMount() {
        document.addEventListener('click', this._onClick);
    }
    componentWillUnmount() {
        document.removeEventListener('click', this._onClick);
    }
    _onClick(event) {
        if (!this.input.current.parentNode.contains(event.target)) {
            this.close();
        }
    }
    componentWillReceiveProps(nextProps) {
        let value = this.state.value;

        if (nextProps.value !== this.props.value && nextProps.value !== value) {
            value = nextProps.value;
        }

        this.setState({
            filtered: this.filter(nextProps.list, value, true),
            value
        });
    }
    close() {
        this.setState({
            open: false,
            filtered: this.unfilter(),
            index: 0
        });
    }
    handleClick() {
        if (this.props.openOnClick) {
            if (this.state.open) {
                this.close();
            } else {
                this.setState({ open: true, filtered: this.unfilter() });
            }
        }
    }
    handleKeyDown(e) {
        const { onKey, useKeys } = this.props;
        onKey(e);

        if (useKeys && this.processKey(e.keyCode)) {
            e.preventDefault();
        }
    }
    processKey(code) {
        const { open, index, filtered, value } = this.state;
        const ssuggestions = filtered.length ? filtered : this.unfilter();
        let nextIndex;

        switch (code) {
            case keys.ENTER:
                if (open && filtered[index]) {
                    this.changeValue(filtered[index].word, true);
                } else {
                    this.setState({ open: true, filtered: this.unfilter() });
                }
                break;
            case keys.ESCAPE:
                this.close();
                if (!open && value) {
                    this.changeValue('');
                }
                break;
            case keys.DOWN:
                nextIndex = (index + open) % ssuggestions.length;
                break;
            case keys.UP:
                nextIndex = (index || ssuggestions.length) - 1;
                break;
            case keys.TAB:
                if (this.props.selectOnTab && open && filtered[index]) {
                    this.changeValue(filtered[index].word, true);
                } else {
                    this.close();
                }
            default:
                return false;
        }

        if (nextIndex !== undefined) {
            this.setState({ open: true, index: nextIndex, filtered: ssuggestions });
        }

        return true;
    }
    handleItemClick({ word }) {
        this.changeValue(word, true);
    }
    handleItemMouseEnter(index) {
        this.setState({ index });
    }
    handleChange(e) {
        e.stopPropagation();
        const value = e.target.value;
        this.changeValue(value);
    }
    remove() {
        this.changeValue('', true);
    }
    changeValue(value, select = false) {
        const { list, suggestOn, accents, onChange, onSelect } = this.props;
        const filtered = this.filter(list, value);
        const suggest = value.length >= suggestOn;
        const open = !!filtered.length && suggest;

        this.setState({ value, filtered, open }, () => {
            onChange(value);
            if (select) {
                const suggestion = filtered.find(({ word }) => transform(accents, word) === transform(accents, value));
                onSelect(value, suggestion && suggestion.item);
                this.close();
            }
        });
    }
    filter(list, value, onlyMatch = true) {
        const { accents, selector } = this.props;
        value = transform(accents, value);

        let mapped = list.map(item => {
            const word = selector(item);
            return {
                index: transform(accents, word).indexOf(value),
                word,
                item
            };
        });
        if (onlyMatch) {
            mapped = mapped.filter(item => item.index !== -1);
        }
        return mapped;
    }
    unfilter() {
        return this.filter(this.props.list, this.state.value, false);
    }
    focus() {
        this.input.current.focus();
    }
    render() {
        const { theme, style, placeholder, arrow, close, tooltip, required } = this.props;
        const { open, value, index, filtered } = this.state;
        const displaySuggestions = open && !!filtered.length;

        return (
            <div className={theme.root} onClick={this.handleClick} onKeyDown={this.handleKeyDown} style={style}>
                <input
                    type="text"
                    className={theme.input}
                    onChange={this.handleChange}
                    value={value}
                    title={tooltip}
                    placeholder={placeholder}
                    required={required}
                    ref={this.input}
                />
                {arrow && <span className={theme.arrow} />}
                {close && value && <span className={theme.close} onClick={this.remove} />}
                {displaySuggestions && (
                    <ul className={theme.list}>
                        {filtered.map((item, i) => (
                            <ListItem
                                key={item.word}
                                theme={theme}
                                item={item}
                                index={i}
                                onItemClick={this.handleItemClick}
                                onItemMouseEnter={this.handleItemMouseEnter}
                                overItem={i === index}
                                search={value}
                            />
                        ))}
                    </ul>
                )}
            </div>
        );
    }
}

Suggestor.propTypes = {
    list: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.object])).isRequired,
    selector: PropTypes.func,
    onChange: PropTypes.func,
    onSelect: PropTypes.func,
    onKey: PropTypes.func,
    value: PropTypes.string,
    openOnClick: PropTypes.bool,
    selectOnTab: PropTypes.bool,
    placeholder: PropTypes.string,
    tooltip: PropTypes.string,
    theme: PropTypes.shape({
        root: PropTypes.string,
        arrow: PropTypes.string,
        close: PropTypes.string,
        list: PropTypes.string,
        item: PropTypes.string,
        activeItem: PropTypes.string
    }),
    suggestOn: PropTypes.number,
    style: PropTypes.object,
    required: PropTypes.bool,
    useKeys: PropTypes.bool,
    accents: PropTypes.bool,
    arrow: PropTypes.bool,
    close: PropTypes.bool
};

Suggestor.defaultProps = {
    theme: {},
    selector: s => s,
    onSelect: noop,
    onChange: noop,
    onKey: noop,
    value: '',
    openOnClick: true,
    selectOnTab: false,
    suggestOn: 1,
    required: false,
    accents: false,
    useKeys: true,
    arrow: true,
    close: true
};

export default Suggestor;

Upvotes: 1

Views: 453

Answers (2)

shobhit1
shobhit1

Reputation: 654

So, looking at the example mentioned in the readme for ssugester package, it looks like you are passing wrong callback for the onSelect method.

So, I believe changing your code to the following way should work.

Change the Suggester component to have a function that represents the onSelect callback in a more meaningful way, for example:

<Suggestor
    id;= "Suggestor";
    list = {suggesttionOldData};
    onSelect = {this.onSuggesterSelect};
    placeholder ='  ...'
    value = {this.state.value}
/ >

and in your NewDataTable component, create another function called onSuggesterSelect.

// GET INPUT VALUE , GET DATA WITH THE SAME NAME IN BOTH ARRAY, CONSOLE.LOG BOTH
onSuggesterSelect(value, suggestion) {
    const val = value; // this should be your selected value (name) now.
    alert(val);
    const consoleOldData = OldData.find(value => value.name);
    const consoleNewData = NewData.find(value => value.name);
    console.log('Old Data =>', consoleOldData);
    console.log('New Data =>', consoleNewData);
}

So, with these changes your component should look something like this:

import React from "react";
import { Component } from "react";
import ReactDOM from "react-dom";
// IMPORT DATA FROM  JSON FILE
import NewData from "../../api/data/cities.json";
import OldData from "../../api/data/historical.json";
// IMPORT PAGINATION FILE
import Pagination from "./Pagination.js";
// IMPORT MODULE TO CREATE INPUT SEARCH
import Suggestor from "ssuggestor";

// CREATE A COMPONENT THAT WILL SHOW THE NEW DATA IN A TABLE
class NewDataTable extends React.Component {
  constructor() {
    super();

    this.state = {
      NewData: NewData,
      pageOfItems: []
    };

    this.onChangePage = this.onChangePage.bind(this);
    this.handleChange = this.handleChange.bind(this);
  }

  onChangePage(pageOfItems) {
    // update state with new page of items
    this.setState({ pageOfItems: pageOfItems });
  }

  // GET INPUT VALUE , GET DATA WITH THE SAME NAME IN BOTH ARRAY, CONSOLE.LOG BOTH
  handleChange(event) {
    var val = document.getElementById(Suggestor);
    alert(val);
    const consoleOldData = OldData.find(value => value.name);
    const consoleNewData = NewData.find(value => value.name);
    console.log("Old Data =>", consoleOldData);
    console.log("New Data =>", consoleNewData);
  }

  onSuggesterSelect(value, suggestion) {
    const val = value; // this should be your selected value (name) now.
    alert(val);
    const consoleOldData = OldData.find(value => value.name);
    const consoleNewData = NewData.find(value => value.name);
    console.log('Old Data =>', consoleOldData);
    console.log('New Data =>', consoleNewData);
  }

  render() {
    // GET DATA.NAME FROM OldData
    const suggesttionOldData = OldData.map(value => value.name);

    return (
      <div>
        <form>
          <Suggestor
            id="Suggestor"
            list={suggesttionOldData}
            onSelect={this.onSuggesterSelect}
            placeholder="  ..."
            value={this.state.value}
          />
        </form>

        <nav>
          <Pagination
            items={this.state.NewData}
            onChangePage={this.onChangePage}
          />
        </nav>
        <table>
          <tbody>
            <tr>
              <th>New Data</th>
            </tr>

            {this.state.pageOfItems.map(item => (
              <tr key={item.id}>
                <td key={item.id}>{item.name}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    );
  }
}

export default NewDataTable;

I hope this works for you now.

Upvotes: 2

June Wenston
June Wenston

Reputation: 124

var val = document.getElementById(Suggestor); Change to var val = event.target.value

Upvotes: 0

Related Questions