question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

RequiredIf with array

See original GitHub issue

First thanks for a great extension - it’s working really well for me, but I have one issue.

I have this on my view model:

    [RequiredIf("QuestionTypeAsString == 'SingleSelect' && Skipped == false && RefusedToAnswer == false", ErrorMessage = "Please complete the answer or select one of the options to skip the question")]
    public int[] SelectedOptionsAnswer { get; set; }

This is posted via a set of checkboxes or radio buttons in the view, and I want to make sure one is selected.

When I step through the code SelectedOptionsAnswer is null, but the model state is valid. Is there a way to get this attribute working with arrays please?

Issue Analytics

  • State:closed
  • Created 9 years ago
  • Comments:12 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
jwaliszkocommented, Jul 16, 2014

Hi,

I predict that your array, even when it contains no elements, is deserialized at server side to non-null (e.g. to empty array or to array containing one default element, hard to say - show your html/js responsible for that). When annotated field is not null, its requirement condition is fulfilled, that’s why model state is valid. The problem may lay in your html I suppose, which sends something to server which is then incorrectly deserialized by MVC.

What you can do is use the other attribute - AssertThat, and write a substitute for RequiredIf logic in your case. This attribute is invoked when annotated field has any value other than null:

[AssertThat("(QuestionTypeAsString == 'SingleSelect' && Skipped == false && RefusedToAnswer == false && ArrayValid(SelectedOptionsAnswer))" +
            "|| QuestionTypeAsString != 'SingleSelect' || Skipped != false || RefusedToAnswer != false", 
             ErrorMessage = "Please complete the answer or select one of the options to skip the question")]
public int[] SelectedOptionsAnswer { get; set; }

as you can see there is ArrayValid method used. This method can be anything which validates the array. Just add this method to your model class:

public bool ArrayValid(int[] arr) { return arr != null && arr.Length > 0; /* or arr.Length > 1, hard to say what you get at server */ }

But take under consideration that this will be working at server side only. If you want this also to work in client side, add this to your view:

<script>
    ea.addMethod('ArrayValid', function (arr) { return arr != null && arr.length > 0; });
</script>

But take under consideration that this client side may not work this time. It’s because everything depends what html is producing.

Regards, Jaroslaw Waliszko

0reactions
jwaliszkocommented, Jan 18, 2016

Instead of referring to this particular example, I can only say that RequiredIf will be invoked only when value is null, AssertThat - when value is not null. It’s the general rule which works the same way at both server- and client-side.

Value parser is an exceptional mechanism, which helps to extract values from HTML, if default selector $('field').val() is not enough (e.g. value distracted among multiple fields), or if value taken with such a default selector is given in some custom format (e.g. "1;2;3", and you need such string value to be parsed into an array [1,2,3]). Its job is to provide the correct value at client-side only. It has nothing to do with server-side. Server-side just works on objects already deserialized by some arbitrary model binder, e.g. provided by MVC framework (in vast majority of cases).

When value parser returns null for an empty array, AssertThat will not be invoked. So, if you’re not using RequiredIf, but AsserThat only, take that under consideration and parse the value accordingly - instead of null return an empty array [].

For example (code is oversimplified to show the difference):

  • here RequiredIf will be fired for an empty array (because null is returned that time):

    ea.addValueParser('ArrayParser', function (value, field) {
        var array = ... // deserialize your DOM extracted value to array object
        return array.length === 0 ? null : array; 
    });
    
  • here forget about RequiredIf, only AssertThat will be invoked (null is never returned):

    ea.addValueParser('ArrayParser', function (value, field) {
        var array = ... // deserialize your DOM extracted value to array object
        return array === null ? [] : array; 
    });
    

I know that it is not that obvious, and can introduce some confusion at the beginning. To understand it better, I can advice to debug through it few times - the good starting points are here (in script v2.6.3):

image

In the end - the data-val-* attributes written by hand is a bad idea whatsoever. They are supposed to be generated automatically by some helpers, powered by the data EA parser produces (after all the type safety checks, etc.). Otherwise, if you’ll change your expression, these data-val* attributes are required to be manually updated as well (which is not a way to work with EA - too much overhead, error prone). If you’d ask me, I’d have resigned from client-side validation support, and relay on server-side one only in such exceptional cases.

Regards

Read more comments on GitHub >

github_iconTop Results From Across the Web

Laravel validation requiredIf with array index - php
I need to apply a required rule to a array field in my form request when the another array field, in the same...
Read more >
required_if validation rule with array values.
I have a form for my admin to create new users. This is where the data is validated: public function rules() { return...
Read more >
Validating arrays and nested values in Laravel
Discover how validating arrays and nested values allows you to more effectively deal with data transmitted from your frontend.
Read more >
Require field only if another field is a non-empty array
I have one field that I need to make required only if another field is a non-empty array. date is required if products...
Read more >
Validators
Checks for empty arrays and strings containing only whitespaces. ... name: { requiredIfFoo: requiredIf(this.foo), requiredIfRef: requiredIf(someRef), ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found