Jump to content

Render field based on their Dependencies


M.O.Z.G
 Share

Recommended Posts

Hello,

I want to know, is there any chance to render only visible fields based on their Dependencies?

For example, I have many fields in template with conditional logic. But all their values stored in DB, and render in loop with $page->$fields.

I could duplicate logic in PHP, but It's seems very inefficient. I couldn't find any API command for such task. Something like flag "isShown". More over, there isn't such flags when I printed array.

I just can't find it, or this data keeps somewhere outside? Or is there some other ability to achieve this?

Thanks for any advise in advance.

Link to comment
Share on other sites

Привет M.O.Z.G! Welcome to the forums!

The dependency data for a field in a fieldset is stored in fields or fieldgroups_fields (if overriden) table in data field in json. So it has to be accessible via standard WireData methods. The name of the property is showIf. Have no chance to try it, but you can get it like

$field->get('showIf');

... and you still have to process that string yourself this way.

I did not find a way to get the visibility of a field dependent on other field via API though. Should be here somewhere if it exists. Try this, but I doubt it will help.

Sorry for no real help) Hope someone more experienced can help out here.

If you would explain your case a little further we could find a workaround. I almost never render through $page->$fields.
 

Link to comment
Share on other sites

Inputfield dependencies are as the name suggests part of the inputfields, which are rendered as part of the backend forms. It's not directly bound to the fields in any way. Also while those dependencies are evaluated by php once when saving a form it's otherwise a pure javascript based evaluation. You could try to create the backend form manually and let it evaluate the show-if statements, but that's really not how it's meant to be used.

Link to comment
Share on other sites

Thank you for the answers, guys!

If you would explain your case a little further we could find a workaround. I almost never render through $page->$fields.

Oh, it's just product options. Product type, and some parameters, which allows/disallows usage of some other fields. For example:

  1. If product_3D_geometry=polys;
  2. than next Integer fields will be shown: product_3D_tris, product_3D_vertex, product_3D_polys;
  3. but product_3D_voxels Integer field will be ignored.

or

  1. If product_3D_geometry=nurbs;
  2. than product_3D_vertex Integer field will be shown;
  3. but next Integer fields will be ignored: product_3D_tris, product_3D_polys, product_3D_voxels.

etc...

Some parameters may change over time, and hidden fields continue to be stored in the database. That's I want to render lines from loop only for actual parameters. Maybe I'm wrong, but don't see a simple solution at the moment.

I had wrote small filter for this task:

function compareCondVals( $fieldName, $op, $fieldValue ) {
//Allowed operators for Inputfield Dependencies
    switch( $op ) {
        case '!=': return !in_array($fieldName, $fieldValue);
        case '=': return in_array($fieldName, $fieldValue);
        case '<=': return $fieldName <= min( $fieldValue ); //I know it is stupid to use multiple values in such cases, but just in case.
        case '<': return $fieldName < min( $fieldValue );
        case '>': return $fieldName > max( $fieldValue );
        case '>=': return $fieldName >= max( $fieldValue );
        case '%=': return $fieldName %= $fieldValue[0];
        case '*=': return $fieldName *= $fieldValue[0];
    }
}

function extractConditionalRule ($conditionString) {
    $patternOperators  = '/>=|>|!==|!=|==|=|\*=|%=|<=|</x';
    preg_match( $patternOperators, $conditionString, $op );
    $op = $op[0];
    $conditionValues = explode( $op, $conditionString );
    $conditionMultiple = explode( "|", $conditionValues[1] );
    $conditionFieldName = $conditionValues[0];
    $conditionFieldObj = wire( 'page' )->get( $conditionFieldName );
    $conditionFieldType = wire( 'page' )->wire( 'fields' )->get($conditionFieldName)->type->name;    
    
    if ( $conditionFieldType == "FieldtypeOptions" ) {
        $conditionFieldValue = $conditionFieldObj->id; //I use IDs for Options fields.
    } else {
        $conditionFieldValue = $conditionFieldObj->value;
    }
    
    return compareCondVals( $conditionFieldValue, $op, $conditionMultiple );
};

function extractMultipleConditionalRules ($conditionArray) {
    $patternSeparator = '/\,\s|\,|\s/';
    $conditionArray = preg_split( $patternSeparator, $conditionArray );
    
    foreach ( $conditionArray as $conditionString ) {
        $conditionSubArray []= extractConditionalRule( $conditionString );
    }

    return min( $conditionSubArray );
}

foreach ($page->fields as $field) {
    $name = $field->name;
    $showIf = $field->showIf;
    ... //Other data here
    $isShown = $showIf != null ? extractMultipleConditionalRules ($showIf) : true;
    
    if ( $isShown ) {
        $fieldsArray[$name] = array(
            ... //Some data here
        );
    }

}
Link to comment
Share on other sites

For basic selectors this would have probably been enough. Though I'm not sure if it covers all edge-cases correctly.

$isShown = $page->is($field->showIf);

Holy crap! It works the same, with no hand!

Thank you LostKobraka, I thought selectors is not "selectors" in this case. I'm still not used to how PW requests all data from the page ... just with simple form of request. It's like a miracle, once again I convinced that.

Thank you again!

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...