mistic100 / jQuery-QueryBuilder

jQuery plugin offering an interface to create complex queries
https://querybuilder.js.org
MIT License
1.68k stars 552 forks source link

Cannot get Value from Rule Object in input of Filter, when loading pre-defined rules. #884

Open mjraval opened 4 years ago

mjraval commented 4 years ago

The Problem:

Accessing the value in the Rule Object always returns undefined. In console.log(rule) , it can be seen that the value property of the rule object has a value. Tried to access it by rule.value and rule["value"]. Both yielding undefined always

jsFiddle : Link

Larger Picture

I am able to show, custom operators, and show the input field as select dropdown or number input according to the operator selected. Its just that when loading pre-defined rules, not able to access value.

Solutions to be achieved

I have custom Code to Deal with Comparing 2 fields of Database. On selecting a specific type of operations , ie the once in FieldsOps group and name ending with an _ , the input would be a dropdown. And also pre populating the values and display the either input box or select.

Effort So Far

  1. Added a new optgroup named FieldOps and made sure all the operators are named the same but just appended with underscore. So, less will becore less_ in the FieldOps optgroup. And set appropriate apply_to. This works perfectly.
{ type: "less_", optgroup: "FieldsOps", nb_inputs: 1, apply_to: [ "number" ] },
{ type: "less_or_equal_", optgroup: "FieldsOps", nb_inputs: 1, apply_to: [ "number" ] },
{ type: "equal_", optgroup: "FieldsOps", nb_inputs: 1, apply_to: [ "number", "string" ] },
{ type: "not_equal_", optgroup: "FieldsOps", nb_inputs: 1, apply_to: [ "number", "string" ] },
{ type: "greater_", optgroup: "FieldsOps", nb_inputs: 1, apply_to: [ "number" ] },
{ type: "greater_or_equal_", optgroup: "FieldsOps", nb_inputs: 1, apply_to: [ "number" ] },
  1. In the filters --> input ,
    {
    id: "3MS1",
    label: "3M Sales S1",
    type: "integer",
    input: function ( rule, name ) {
        return input_creator_fieldComparison( rule, name );
    },
    valueGetter: function ( rule ) {
        return valueGatter_fieldComparison( rule );
    },
    },
  2. Definition of valueGetter and input functions in the filters.

    
    function input_creator_fieldComparison( rule, name ) {
    
     let value = rule.value;
    let myOptGroup = rule.operator.optgroup;
    let show_select = ( myOptGroup == "FieldsOps" );
    let show_text = !show_select;
    let htmlOut = "<select name = \"" + name + "_1\" class = \"form-control value-select\"" + ( show_text ? " style = \"display: none;\"" : "" ) + " onchange=\"data_from_select(this)\"" + ">";
    htmlOut += getComparableCoumnsDropDownOptions(selectedOption);
    htmlOut += "</select>";
    htmlOut += "<input name = \"" + name + "_2\" class = \"form-control value-text\" type = \"text\"" + ( show_select ? " style=\"display: none;\"" : "" ) + "onchange=\"data_from_text(this)\" onkeyup=\"data_from_text(this)\"" + " value=\""+value+"\"></input>";
    
    return htmlOut;
    }

function valueGatter_fieldComparison( rule ) { return rule.$el.find( ".rule-value-container" ).attr( "data-value" ); }

4. Definition of additional Helper Function in the custom HTML from `input`

data_from_select = function ( id ) { $( id ).parent().attr( "data-value", $( id ).find( ":selected" ).val() ); };

data_from_text = function ( id ) { $( id ).parent().attr( "data-value", $( id ).val() ); };


### The Problem:
Accessing the `value` in the `Rule` Object in  `input_creator_fieldComparison` always returns `undefined`. This is necessary when loading pre defined rules from the last request, after sending a set of rules and then in response loading the resulting set in a table.

Any pointer would be highly appreciated.
mistic100 commented 4 years ago

Please create an jsfiddle or similar

mjraval commented 4 years ago

@mistic100 , Thanks for the Quick response. Sorry, took a while to put that in place. Edited the Comment and added link to jsFiddle.

jsFiddle : Link

Akash-JS commented 4 years ago

Hello @mjraval ,

In order to set predefined value you should use the "valueSetter".

valueSetter: function (rule) { setRuleValue(rule); }

So your filter --> input will be,

{
    id: "3MS1",
    label: "3M Sales S1",
    type: "integer",
    input: function ( rule, name ) {
        return input_creator_fieldComparison( rule, name );
    },
    valueGetter: function ( rule ) {
        return valueGatter_fieldComparison( rule );
    },
       valueSetter: function ( rule )
        {
            setRuleValue(rule);
        }
}

function setRuleValue(rule)
{
 **// You can customize this method based on your requirements.**
    if (rule.operator.optgroup !== null)
    {
        rule.$el.find('.rule-value-container select:first').val(rule.value);
    }
    else
    {
        var valueContainer = rule.$el.find('.rule-value-container');
        if (rule.operator.nb_inputs <= 1)
        {
            var input = valueContainer.find('input');
            if (input.length === 0)
            {
                input = valueContainer.find('select:not(:first)');
            }

            input.val(rule.value);
        }
        else
        {
            var index = 0;
            valueContainer.find('input').each(function ()
            {
                $(this).val(rule.value[index]);
                index++;
            });
        }
    }
}

Hope this will help...

danclay91 commented 3 years ago

Did you end up being able to solve this? I am encountering this as well.

danclay91 commented 3 years ago

In one case, I am trying to access rule.value on a successful ajax request, in this situation rule.value works. But if I try to call it before that ajax call, it is undefined.