apply css by checking if value exists

Viewed 112

I have an array with objects inside. What I'm trying to do is loop through the array and check if a value exists by key and if it does apply a CSS to a div but right now even though the value exists the specified CSS doesn't apply it just applies the "else" CSS. Why is this happening and how can I fix it? Thanks in advance.

let testArray = [{"length": "None", "duration": "10000", "percentage": "65"}, {"width": "Half", "detail": "under", "duration": "25000", "percentage": "25"}, {"length": "Full", "duration": "20000", "percentage": "90"}]

testArray.forEach((obj) => {
  if (obj.length?.toLowerCase() == 'none') {
    $('.test').css('background-color', 'red')
  } else {
    $('.test').css('background-color', 'blue')
  }
});
.test {
  width: 30%;
  height: 40%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='test'>
  <p>testing</p>
</div>

4 Answers

It's changing to red as the first value is equal to none but the next two values are not equal to none so it's changed back to blue twice so when you get the objects in the loop you have to go through them again to check if any property has a value None and then break out of the two loops.

 let testArray = [{"length": "None", "duration": "10000", "percentage": "65"}, {"width": "Half", "detail": "under", "duration": "25000", "percentage": "25"}, {"length": "Full", "duration": "20000", "percentage": "90"}]
    let checkIfNoneIsFound=0;
    testArray.every((obj) => {
    Object.values(obj).every((val)=>{
     if(val.toLowerCase()=='none'){
       $('.test').css('background-color', 'red');
       checkIfNoneIsFound+=1;
       return false;
       }
       return true;
    })  
    if(checkIfNoneIsFound==1)
    {
      return false;
    }
     $('.test').css('background-color', 'blue') 
     return true;
  });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class='test'>
      <p>testing</p>
    </div>

yor code loops through the obj and changes the background-color each time, in the last it is changed to red,

try doing this:

let testArray = [
{"length": "none", "duration": "10000", "percentage": "65"}, 
{"width": "Half", "detail": "under", "duration": "25000", "percentage": "25"}, 
{"length": "Full", "duration": "20000", "percentage": "90"}]

testArray.forEach((obj) => {
    
  
  if (obj.length?.toLowerCase() == 'none') {
    var para = document.createElement("p");
    para.setAttribute("id", obj.index);
    para.setAttribute("class", "red");
    para.innerText = obj.percentage;
    $(".test").append(para);
  }
  else if (obj.length?.toLowerCase() == 'full') {
    var para = document.createElement("p");
    para.setAttribute("id", obj.index);
    para.innerText = obj.percentage;
        para.setAttribute("class", "gray");
    $(".test").append(para);
  } else {
    var para = document.createElement("p");
    para.setAttribute("id", obj.index);
    para.innerText = obj.percentage;
        para.setAttribute("class", "yellow");
    $(".test").append(para);
  }
  
});
.red{
  background: red
}
.gray{
  background: gray
}
.yellow{
  background: yellow
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='test'>

</div>

The easiest way on this case is use a frontent framework, like react, handlebars, etc..

The think is, on these frameworks you will render your code depending in the result, like this for react: (note that this is directly on the HTML)

{testArray.map(()=>{
  (obj.length?.toLowerCase() == 'none' )
  ? <div>Some info</div>
  : <div>Some different info</div>
})}

"What you want to achieve is applying the red background when the value exists in any of the elements of the array, otherwise to apply the blue background, can you confirm?" – Rigoberto Ramirez Cruz

"@RigobertoRamirezCruz yeah" – seriously

Needed to post that because the question wasn't clear. The following example is a reusable function. The result looks like this in HTML:

<mark style="color:red">0</mark>  <!-- {"length": "None",    -->
<mark style="color:blue">0</mark> <!--  "duration": "10000", -->
<mark style="color:blue">0</mark> <!--  "percentage": "65"}, -->
<mark style="color:blue">1</mark> <!-- {"width": "Half",     -->
<mark style="color:blue">1</mark> <!--  "detail": "under",   -->
<mark style="color:blue">1</mark> <!--  "duration": "25000", -->
<mark style="color:blue">1</mark> <!--  "percentage": "25"}, -->
<mark style="color:blue">2</mark> <!-- {"length": "Full",    -->
<mark style="color:blue">2</mark> <!--  "duration": "20000", -->
<mark style="color:blue">2</mark> <!--  "percentage": "90"}; -->
<!--
This is the result if "length" and "None" were the 2nd and 3rd @param 
(the only <mark> that has red text)
-->

Details are commented in example

let testArray = [{"length":"None","duration":"10000", "percentage":"65"}, 
{"width":"Half","detail":"under","duration":"25000","percentage":"25"}, 
{"length":"Full","duration":"20000","percentage":"90"}];

// Reference the element that'll display results
const test = document.querySelector('.test');

/**
 * @desc - Given an array of objects, a key and a value, generate a <mark>
 * with an index of the current object for each key/value pair. 
 * If a pair matches the 2nd and 3rd @param the index will be red.
 * @param {array<object>} array - An array of objects
 * @param {string} key - The first string of a pair representing a property 
 *                       name
 * @param {string} val - The second string of a pair representing a value
 * @param {object<DOM>} node - The DOM Object that the results will be 
 *                             displayed in @default is <body>
 */ 
function findKV(array, key, val, node = document.body) {  
  // Prepare key/val for comparison -- matching is case insensitive
  key = key.toLowerCase();
  val = val.toLowerCase();
  // For each object of the array...
  array.forEach((obj, idx) => {
    /*
    Convert object into an array of pairs -- pass the destructed 
    [key, value] array pair
    */
    Object.entries(obj).forEach(([k, v]) => {
      /*
      Compare with a ternary:
      If key equals k AND val equals v color is red -- otherwise it's blue
      */
      let color = key === k.toLowerCase() && val === v.toLowerCase() ?
      'red' : 'blue';
      /*
      Generate a <mark> with an index of current object with the
      appropriate color
      */
      node.innerHTML += 
      `<mark style='color:${color};font-size:4rem;'>
         ${idx}
       </mark>`;
    });
  });
  // Add a line-break
  node.innerHTML +=`<br>`;
}

findKV(testArray, 'length', 'None', test);
findKV(testArray, 'percentage', '25', test);
findKV(testArray, 'duration', '20000', test);
html {font: 400 1ch/1 Consolas}
.test {outline: 4px dashed brown}
<div class='test'></div>

Related