3

I have an app that has gazillions of fields where some are are 'required' and some aren't and doing it using jQuery seems performance intensive. So I tried doing it using css but to no avail. So I have turned here to Stack Overflow! :)

Let me put the code and try to explain what I want to achieve.This is from a Kendo UI for MVC wrapper, so it has some Kendo classes but it shouldn't change anything.

This is what the wrapper code looks like when the page is first loaded (in the Chrome debug window). At this point, i.e. when the page is first loaded, I want to show the user the asterisk on all the required fields.

<div class="form-group">
    <label><b>Phone</b></label>
    <div>
        <span class="k-widget phonenumber">
        <input required="required" data-val="true" data-val-required="The Phone field is required." id="PhoneNumber" >
    </div>
</div>

There's a validator defined as follows which dynamically adds/ removes error classes to the form elements.

var $validator = $("#form").validate({
    highlight: function (element) {
        $(element).closest('.form-group').removeClass('has-success').addClass('has-error');
    },
    unhighlight: function (element) {
        $(element).closest('.form-group').removeClass('has-error').addClass('has-success');
    },
    errorElement: 'span',
    errorClass: 'help-block',
    errorPlacement: function (error, element) {
        if (element.parent('.input-group').length) {
            error.insertAfter(element.parent());
        } else {
            error.insertAfter(element);
        }
    }
});

So currently, when the user clicks on this field and loses focus, the code looks like this:

<div class="form-group has-error">
    <label><b>Phone</b></label>
    <div>
        <span class="k-widget phonenumber">
        <input required="required" data-val="true" data-val-required="The Phone field is required." id="PhoneNumber" >
        <span for="PhoneNumber" class="help-block">This field is required.</span>
    </div>
</div>

So the div gets has-error class and a span is added to show the error message.

When we fulfil this requirement by typing something in this field, the error message is hidden and the error class is removed and has-success class added and the code looks like this:

<div class="form-group has-success">
    <label><b>Phone</b></label>
    <div>
        <span class="k-widget phonenumber">
        <input required="required" data-val="true" data-val-required="The Phone field is required." id="PhoneNumber" >
        <span for="PhoneNumber" class="help-block" style="display: none;">This field is required.</span>
    </div>
</div>

So looking at this behavior of these elements, is there a way to find elements that have the 'required' attribute, go one step up to find their label and put a * after them. And when the form has no error class, removing that * again? I'm clueless to finding that kind of css selector! :(

I have done it using jQuery, it works, but I still don't like it as the form is so dynamic and I need to call this AstAdd() method whenever the elements' required attribute change. css way would have been way cleaner.

function AstAdd(){
    $('input[required]').each(function () {
        AstToggle($(this));
        $(this).blur(function () {
            AstToggle($(this));
        });
    });
}
function AstToggle(element) {
    if (element.val() == '') {
        element.closest(":has(label)").find('label').addClass('Asterisk');
    } else {
        element.closest(":has(label)").find('label').removeClass('Asterisk');
    }
}

And create a css class like this:

.Asterisk:after {
    content: " *";
    color: red;
}

Thank You very much for the help!

Ash K
  • 1,802
  • 17
  • 44
  • have you looked at this? https://paulund.co.uk/add-required-asterisk-with-css – Waldir Bolanos Jun 13 '19 at 19:07
  • Hi @Waldir, thank you for the link but that doesn't work for me as my – Ash K Jun 13 '19 at 19:13
  • So how exactly are you adding and deleting classes? Surely its using jQuery, if so you can use it to add the required class as-well. – Waldir Bolanos Jun 13 '19 at 19:25
  • Hi @Waldir Bolanos, this behavior of adding/ removing classes is done by the internal working of the Kendo UI for ASP.NET MVC wrapper. Sure it's done by the jQuery inside the wrapper which I have no control over with but I don't want to add more jQuery to it now. Thank You. – Ash K Jun 13 '19 at 19:31
  • I see, what about selecting the 'has-error' class and doing the same thing as the article above but with the label. https://jsfiddle.net/wwWaldi/vzj8co25/15/ – Waldir Bolanos Jun 13 '19 at 19:35
  • We use the linked to css class method. Then you use kendo's `HtmlAttribute` methods on the various wrappers to add the classes. – Steve Greene Jun 13 '19 at 19:48
  • @Waldir, That's great start, thank you but I also want all the asterisks to show up when the page loads (when we don't even have the 'has-error' class). This time we need to show this asterisk by going through the input elements that have required attribute and moving to their label to put an asterisk. – Ash K Jun 13 '19 at 19:49
  • 2
    If ALL the fields are required this can be done using the same method i showed, but if some are and some aren't this is impossible with pure CSS because it can't go backwards. – Waldir Bolanos Jun 13 '19 at 19:59
  • @WaldirBolanos Yes some fields are required and some aren't and they often change dynamically. So I guess, I'm out of luck?! :( – Ash K Jun 13 '19 at 20:07

1 Answers1

2

Can sort of do this with CSS using Psuedo Elements and content.

input[required] {
  display: block;
}

input[required]::after {
  content: '*';
  color: red;
}
<label><b>Phone Number</b></label>
<div>
  <span class="k-widget phonenumber">
        <input required="required" data-val="true" data-val-required="The Phone field is required." id="PhoneNumber" >
    </div>
</div>
<div class="form-group">
    <label><b>Mobile Number</b></label>
    <div>
        <span class="k-widget phonenumber">
        <input id="MobileNumber" >
    </div>
</div>
<div class="form-group">
    <label><b>Office number</b></label>
    <div>
        <span class="k-widget phonenumber">
        <input id="OfficeNumber" >
    </div>
</div>

It looks like there is a bug of sorts for this. See more: Combine CSS Attribute and Pseudo-Element Selectors?

I would strongly advise using jQuery as it it allows a lot more options.

$(function() {
  $("[required]").after($("<span>", {
    class: "required"
  }).html("*"));
});
.required {
  color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="form-group">
  <label><b>Phone Number</b></label>
  <div>
    <span class="k-widget phonenumber">
        <input required="required" data-val="true" data-val-required="The Phone field is required." id="PhoneNumber" >
    </div>
</div>
<div class="form-group">
    <label><b>Mobile Number</b></label>
    <div>
        <span class="k-widget phonenumber">
        <input id="MobileNumber" >
    </div>
</div>
<div class="form-group">
    <label><b>Office number</b></label>
    <div>
        <span class="k-widget phonenumber">
        <input id="OfficeNumber" >
    </div>
</div>

Hope that helps.

Twisty
  • 30,304
  • 2
  • 26
  • 45
  • Hi @Twisty, thank you so much for the answer. I have just updated my question to be more clear and what I've done in my jQuery code is what I want to achieve but I want to do it using css. Basically, find elements that have the 'required' attribute, go one step up to find their label and put a * after them. And when the form has no error class, removing that * again. Thank you for your help! – Ash K Jun 17 '19 at 20:29
  • @AshK there are no parent selectors in CSS, not even in CSS3. Not possible with CSS alone. – Twisty Jun 17 '19 at 21:26