wingsuit-designsystem / wingsuit

Twig for Storybook
GNU General Public License v2.0
91 stars 16 forks source link

Extension to provide new object based multi_value_type for pattern lists #154

Closed jowan closed 3 years ago

jowan commented 3 years ago

Is your feature request related to a problem? Please describe. Feature Request : The ability to have new "multi_value_type:named_object" type for pattern list.

Describe the solution you'd like In Drupal I have a template like this:

{{ form.error_messages }}
<div class="row">
  <div class="col-md-6">{{ form.station_origin }}</div>
  <div class="col-md-6">{{ form.station_destination }}</div>
</div>
<div class="row">
  <div class="col-md-6">{{ form.times }}</div>
  <div class="col-md-6">{{ form.week_day }}</div>
</div>
{# Renders the rest of the form #}
{{ form|without('error_messages','station_origin','station_destination','times','week_day') }}

I would like to define this in my-form.wingsuit.yml as follows:

  fields:
    form:
      type: pattern
      label: Form
      multi_value_type: named_object
      preview:
        station_origin:
          variant: "checkbox"
          settings:
            label_display: after
        station_destination:
          variant: "checkbox"
          settings:
            label_display: after

So that I can represent the fields similar to how they are represented in Drupal.

Describe alternatives you've considered I have tried using 'object' instead of 'pattern' for 'type' but that means referencing a sub-templare and passing varibles (not happy with that). and have tried 'single_value' and 'items' when using 'pattern' but I can not access the values in the way I would like.

Additional context I presume this is relativley simple, as the 'items' array is very close, just not an object with named attributes. Is there a way to create my own Extension that would handle this ?

Thanks

christianwiedemann commented 3 years ago

Hi, not sure but maybe "type: object" works for you. https://wingsuit-designsystem.github.io/components/wingsuit/#type-object or check the menu component. If not, let me know.

jowan commented 3 years ago

The object type is just data and you can do what you want with it, like pass to a sub-template, which is great. I use this a fair bit.

I want to use the pattern type, and just print out {{ my_pattern }}, but I don't want an array. I want an object of patterns - because that is how I am rendering in Drupal.

I have got this working, and it's pretty useful for my use case.

in pattern/dist/Field.d.ts - I added named_object:

export declare enum MultiValueTypes {
    items = "items",
    field_items = "field_items",
    single_value = "single_value",
    named_object = "named_object"
}

in /pattern/dist/Field.js - I added named_object:

(function (MultiValueTypes) {
  MultiValueTypes["items"] = "items";
  MultiValueTypes["field_items"] = "field_items";
  MultiValueTypes["single_value"] = "single_value";
  MultiValueTypes["named_object"] = "named_object";
})(MultiValueTypes || (exports.MultiValueTypes = MultiValueTypes = {}));

in pattern/dist/twigRenderEngine.js - I added a clause for that type:

if (variant.getField(fieldName).multiValueType() === _Field.MultiValueTypes.named_object) {
  if (previewRenderedVariables[nameKeys[0]] === undefined) {
    previewRenderedVariables[nameKeys[0]] = {};
  }
  var item = variant.getField(fieldName);
  if (item.preview[delta] !== undefined && item.preview[delta].hasOwnProperty('name')) {
    var item_name = item.preview[delta].name;
    previewRenderedVariables[nameKeys[0]][item_name] = promisedPreviewValues[j];
  }
}

It's just an object rather than an array. This means I can define my pattern children in yml like this:

  fields:
    form:
      type: pattern
      label: Form
      multi_value_type: named_object
      preview:
        - id: form_element
          name: station_origin
          variant: "checkbox"
          settings:
            label_display: after
        - id: form_element
          name: station_destination
          variant: "checkbox"
          settings:
            label_display: after

and access them like this:

<div class="row">
  <div class="col-md-6">{{ form.station_origin }}</div>
  <div class="col-md-6">{{ form.station_destination }}</div>
</div>

which is great. This template is now compatible with the backend developers custom module and template.

Please forgive the hacky code - there is probably a much better way to do this :)

jowan commented 3 years ago

The docs code is definitely not right though !

{% include "@organisms/tm-lbt/form/form.twig" with {
  "form--0": null,
  "form--1": null,
  "form--2": null,
  "form--3": null,
  "form--4": null
} %}

Is there a way I can affect this output ? it should just have one form entry.