Home>

We are creating a site with a search function using Underscore.js and json.

I was able to implement the Rect Box using the following site as a reference.
I would like to search for multiple selections using the multi select box.
It's immature and it doesn't work.

Search for a value that includes red and blue in"color" ;.

Can you ask if there is anyone who can teach me?
Thanks for your cooperation.

<form id ="search"name ="search">
Color
<select name ="color"id ="color">
<option value ="">Not specified</option>
<option value ="red">Red</option>
<option value ="blue">blue</option>
<option value ="green">Green</option>
</select>

Shape
<select name ="type"id ="type">
<option value ="">Not specified</option>
<option value ="square">square</option>
<option value ="circle">circle</option>
</select>

<input type ="submit"value ="Search">
</form>

<div id ="items"></div>

var items = [
{
"name":"red square" ;,
"color":"red" ;,
"type":"square"
},
{
"name":"red circle" ;,
"color":"red" ;,
"type":"circle"
},
{
"name":"blue square" ;,
"color":"blue" ;,
"type":"square"
},
{
"name":"blue circle" ;,
"color":"blue" ;,
"type":"circle"
},
{
"name":"Green Square" ;,
"color":"green" ;,
"type":"square"
},
{
"name":"Green Circle" ;,
"color":"green" ;,
"type":"circle"
}
];

// What happens when search is pressed
$('# search'). on ('submit', function (event) {
// Cancel the default event
event.preventDefault ();

// Create search object and store select box value
var query = {};
if ($('# color'). val ()! ='') {
query.color = $('# color'). val ();
}
if ($('# type'). val ()! ='') {
query.type = $('# type'). val ();
}

// Find matching objects in data
var results = _.where (items, query);

// Output processing with the returned array
outputResults (results);
});

// Search result output processing
function outputResults (results) {
// variable initialization
var html ='&apos ;;

// Loop the received array
// Formatting the output HTML
jQuery.each (results, function () {
html + ='<div class ="item'+ this.color +''+ this.type +'">&apos ;;
html + = this.name;
html + ='</div>&apos ;;
});

// Output to HTML
$('# items'). empty (). append (html);
}

// Output all items when page loads
$(window) .on ('load&apos ;, function () {
outputResults (items);
});

  • Answer # 1

    Hello.

    First of all,lodash'swhereis

    https://github.com/lodash/lodash/wiki/Deprecations

    As described in

    , it has been removed from v4 and is supposed to use filter instead.

    If you have any questions

      

    I want to search by selecting multiple items in the multi select box

    It is

    . In that case, it can be realized by giving a function that returnstrueorfalseto the second argument of filter depending on whether or not it matches the condition. I can do it.
    An example of a specific amendment is given below. For single selection, just like the code in the question,

    // Search for matching objects in the data
        var results = _.filter (items, query);


    I think that it should be corrected as follows.

    // Search for matching objects in the data
        var results = _.filter (items, function (item) {
          return (
            (query.colors.includes ("") || query.colors.includes (item.color))&&
            (query.types.includes ("") || query.types.includes (item.type))
          );
        });
    If

    selectcan be selected more than once,.val ()sets the value of the selected<option>It becomes an array as an element.

    Therefore, the<select>id andqueryproperty namescolorandtypeshould be pluralized ascolorsandtypes.

    For

    query.colorsandquery.types, use include andtrue for all items that satisfy the condition Pass a function that returnsto the second argument offilter.

    The above sample was created below. (The lodash version used is 4.17.10)

    Single selection: https://jsfiddle.net/jun68ykt/qw64naub/28/

    Multiple selection: https://jsfiddle.net/jun68ykt/qw64naub/68/

    I would be pleased if it was helpful.


    Append

    If you pass a function as the second argument of_. filter, you can write the following using JavaScript's standard Array.prototype.filter () The In this case, lodash is unnecessary.

    // Search for matching objects in the data
        var results = items.filter (function (item) {
          return (
            (query.colors.includes ("") || query.colors.includes (item.color))&&
            (query.types.includes ("") || query.types.includes (item.type))
          );
        });

    Appendix 2

    When multiple selections are possible, added answers to colorsand types, and the plural is better.


    Appendix 3

    Commented in the comments,

      

    Is it possible to link other options with "Not specified"?

    .when<select>changes which<option>is selected You can do this by setting the desired processing in the chageevent handler.

    Specifically, for example, add the following.

    // If "Not specified" is selected, no other options are selected
      $('select'). on ('change', function () {
        if ($(this) .val (). includes (""))
          $(this) .val ([""]);
      });

    Adding the above has the following effects.

    For example, assume thatredandgreenare selected, and thatnot selectis selected . Then thechangehandlerfunction () {…}set above is called, and$(this) .val ()>Will result in an array of values ​​for the selectedoption, so in the current situation,["" ;,"red" ;,"grren"]and three elements. Among these elements, the empty string""is included (=.includes (" ;")is true), it means that "not specified" was chosen. In that case, an array[""]indicating that only "not specified" is selected is replaced with$(this) .val (setting value)If set to, other options that are not "not specified" can be left unselected.

    * The following sample was created.

    https://jsfiddle.net/jun68ykt/qw64naub/81/


    Appendix 4

    From the comments,

      

    I'm sorry many times, if possible
      ...

    This is a way to fulfill the additional requirements given.

    To satisfy the desired behavior, save the<option>value array that was selected when thechangeevent occurred. , The<option>value array that is selected when the next newchangeevent occurs, and the previouschange you savedI think that it will be necessary to compare with the array of values ​​that were selected when the event occurred, create the next desired state, and then save it again. Where to save, one idea is to save it in thedata-attribute.

    The conditions to be judged by the above comparison are

    Whether[""]is the array of values ​​that were finally selected when the lastchangeevent occurred

  • . The following is an example of the above implementation. Lodash's isEqual is used to determine whether the previous selected value is[""].

    // Setting when option selection status is changed
      $('select')
        .data ('prev-values', [""])
        .on ('change', function () {
          if ($(this) .val (). includes ("")) {
            if (_.isEqual ($(this) .data ('prev-values'), [""])) {
              $(this) .val ($(this) .val (). filter (v =>v! = ""));
            } else {
              $(this) .val ([""]);
            }
          }
          $(this) .data ('prev-values', [... $(this) .val ()]);
       });

    The above sample

    https://jsfiddle.net/jun68ykt/qw64naub/95/

    Created in

    .


    Add 5

    The topic "How can I get the value before the target change event occurs in the onChange handler" is also posted below.

    stackoverflow: Getting value of select (dropdown) before change

    In the above answer, thedata-attribute is used as a place to save the selected value when thechangeevent occurs. There are some.


    Appendix 6

    The following part of the code written in appendix

    $(this) .val ($(this) .val (). filter (v =>v! = ""));


    Can be shortened a bit by writing:

    $(this) .val ($(this) .val (). filter (v =>v));

  • Answer # 2

    Excuse me, if possible, if you select "Not specified" and select "Red", "Blue", etc., can you deselect the option not specified?