Search code examples
javascripthtmlnode.jsif-statementelectron

Why does my 'includes' statement require the entire string?


I am trying to use an 'if includes' statement within my Node JS project to filter the results pulled from a .txt file. The idea is that the serial number a user inputs correlates to specific models from the first 5 numbers so I would like to filter the data that gets put into my HTML <select> however it seems to only work if the entire string is identical. Perhaps I'm wrong (I'm very new to JS so I very well could be) but it's my understanding that .includes should be 'if X contains Y' and not 'if X = Y'. I have used it elsewhere in my project with text inputs and it does not behave this way.

<div class="col-md-12 text-center serialtab">
    <h1>Serial Number:</h1>
    <input type="text" minlength="10" required id="serialnumberinput" name="serialnumberinput" class="serialtextbox" placeholder="Type Serial Number Here: 19180-12345">
    <button type="submit" class="buttonalt serialsubmit" id="serialsubmit" onclick="ReadSerials(), PopulateModelList();">SUBMIT</button>
</div>

....

<select class="fixselect" name="model" id="model" onchange="ReadModels()">
    <option value="" selected="selected" >Select Model</option>
    <!-- Models are added from the modelist.js script from the model.txt file -->
</select>
function PopulateModelList() {
    const fs = require("fs");
    const { parse } = require("csv-parse");

    var modellist = document.getElementById('model');
    var serial = document.getElementById("serialnumberinput").value; //I have tried without .value also
    var serialmodel = serial.substring(0,5); //Adding .value to this results in 'undefined'

    var testing = document.getElementById("modeltesting");
    testing.innerHTML += serialmodel; //Outputs '19180'

    fs.createReadStream("./model.txt") //Tried using it as a .csv also but it did not change anything
    .pipe(parse({
        delimiter: ",",
        from_line: 1,
    }))

    .on("data", function(row) {
        console.log(row);
        
        if (row.includes(serialmodel)) {
            modellist.innerHTML += '<option value="' + row + '">' + row + '</option>' ;
        }

        else {

        }
    })
}

My 'serialmodel' var outputs '19180' and the line this should call from .txt file is '19180 - Testing'. If I change my HTML to allow text input and type the full line '19180 - Testing' into the 'serialnumberinput' field then the function works as intended so it seems to be require the entire string to match. I have tried using indexOf instead however this just outputs the entire file. I've tried a number of other workarounds I found from other forum posts too however I'm picking this project back up after a hiatus so cannot remember what exactly those were, apologies.


Solution

  • Presumably, your CSV parser is providing row as an array of cell values.

    From MDN on Array.prototype.includes():

    The includes() method compares searchElement to elements of the array using the SameValueZero algorithm.

    TLDR: The array method is looking for a whole value -not a partial value.

    If you want to check if any string element in the array contains a substring, you could use Array.prototype.some() coupled with String.prototype.includes(), e.g.:

    const row = [true, Infinity, "19180 - Testing", null, "foo"];
    const serialModel = "19180"
    const containsSerialModel = row.some(cellValue => 
      typeof cellValue === "string"
      && cellValue.includes(serialModel)
    );
    console.log(`"${serialModel}" ${containsSerialModel ? "found" : "not found"}`);