1

I have a MVC project that I'm using Ajax to update a section of a View that includes a FontAwesome 5 icon. FontAwesome is set using CSS class so I assumed that I could easily remove and then add the CSS for the icon. However, when I try making the CSS change through jQuery the CSS never get's set. The add/remove class works as expected on the regular CSS class I'm changing but not on the FA class valid-icon.

This is the initial HTML:

@if (Model.VALID_FLAG == "Y")
{
    <div class="validation__text-success" id="valid-flag>
        <i class="fas fa-check-circle" id="valid-icon"></i> Yes
    </div>
}
else
{
    <div class="validation__text-danger" id="valid-flag>
        <i class="fas fa-times-octagon" id="valid-icon"></i> No
    </div>
}   

This is the jQuery from the Ajax call.

var $html = $(response);
if ($html.hasClass('alert-success')) {
    $("#valid-flag").text('Yes');
    $("#valid-flag").removeClass().addClass('validation__text-success');
    $("#valid-icon").removeClass().addClass('fas fa-check-circle');
}
else if ($html.hasClass('alert-danger')) {
    $("#valid-flag").text('No');
    $("#valid-flag").removeClass().addClass('validation__text-danger');
    $("#valid-icon").removeClass().addClass('fas fa-times-octagon');
}
Caverman
  • 3,371
  • 9
  • 59
  • 115
  • 1
    Also, `text()` replaces all the content, including the icon element. – showdev Oct 09 '18 at 19:52
  • The HTML snippet was added just to help with the understanding of what I'm doing. The second snippet is the Ajax which looks at the response, reads it as HTML, and then looks for a Bootstrap class in the returned HTML of either alert-success or alert-danger. Depending on which class is found the jQuery should determine what text and icon I display on another section of the page. – Caverman Oct 09 '18 at 19:57
  • @showdev, ahhh....that's probably what's doing it. When I inspect the element the tag for the FontAwesome is just missing so it makes since that you say text() replaces it all. I tried adding the tag and it's corresponding FA class but it just displayed as raw HTML. That's what led me back to trying to just change the CSS class for the FA icon. – Caverman Oct 09 '18 at 20:00
  • I was asking for the HTML mostly because I suspect that your script could be simplified. If you care to post just the rendered markup for `$html`, we could have a look. – isherwood Oct 09 '18 at 20:04
  • If you're adding HTML, use `html()` instead of `text()`. Another option is to wrap the text content of `#valid-flag` in an element, e.g. `Yes`. That way, you can replace the text without replacing the icon. – showdev Oct 09 '18 at 20:04
  • Also also, it's not ideal to rely on classes being present in your markup. Instead, rely on the status of the api return payload. I'm guessing that there's something there to catch. – isherwood Oct 09 '18 at 20:06
  • @isherwood, I agree, I would prefer to not rely on CSS class being present as to what to do but the code that is being returned to me is a Bootstrap alert and that's it. I would have to jump through hoops to get something else returned to me. – Caverman Oct 09 '18 at 20:12
  • 1
    @showdev, using html() worked. I should have known that one. I didn't realize text() replaced everything with just the text so that is good one to know for future stuff. – Caverman Oct 09 '18 at 20:19

1 Answers1

1

The text() method replaces all text content, including the icon element.
It seems that you've opted for html() to replace the icon element and text label at the same time.

Another alternative solution is to modify a specific text node of the element, using contents().
I found this idea in this answer by charlietfl.

Note that, in my example below, duplicate IDs are added to the page. But this is only for demonstration, given that you cannot change the HTML code returned by your response.

var response = [
  `<div class="alert-success" id="valid-flag">
     <i class="fas" id="valid-icon"></i> ???
   </div>`,
  `<div class="alert-danger" id="valid-flag">
     <i class="fas" id="valid-icon"></i> ???
   </div>`
];

function processResponse(response) {

  var $html = $(response);

  if ($html.hasClass('alert-success')) {

    $html.contents().last()[0].textContent = 'Yes';
    $html.removeClass().addClass('validation__text-success');
    $('#valid-icon', $html).removeClass().addClass('fas fa-check-circle');

  } else if ($html.hasClass('alert-danger')) {

    $html.contents().last()[0].textContent = 'No';
    $html.removeClass().addClass('validation__text-danger');
    $('#valid-icon', $html).removeClass().addClass('fas fa-frown');

  }

  $('body').append($html);

}


$.each(response, function(i, v) {
  processResponse(v);
});
.validation__text-success {
  background-color: lightgreen;
}

.validation__text-danger {
  background-color: pink;
}

#valid-icon {
  margin: 0 .5em 0 0;
}
<link href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
showdev
  • 28,454
  • 37
  • 55
  • 73
  • 1
    I actually just used the following $("#valid-flag").html(' No'); OR $("#valid-flag").html(' Yes'); – Caverman Oct 09 '18 at 20:44