kirakiray/ofa.js

[discuss] How to dynamically render different content based on the value of the item in a loop?

frmachao opened this issue · 2 comments

ofa.js version 4.1.8

ofa.js is really great, but I've encountered an issue while using it and I hope you can help me out.

description:

I have an ofa.js component which is working fine. x-fill renders corresponding items based on the list array.

<!-- fill-demo.html -->
<template component>
    <h3>x-fill demo</h3>
    <div id="fill-container" style="padding: 16px; background-color: #eee">
      <x-fill name="fillTemplate" :value="list"></x-fill>
    </div>
    <template name="fillTemplate">
      <div class="fill-item" style="margin: 10px; padding: 10px; border: red solid 1px">
        {{ $data }}
      </div>
    </template>
  
    <script>
      export const tag = "fill-demo";
      export const data = {
        list: ['eat', 'sleep', 'coding']
      };
    </script>
  </template>

image

However, now I want to dynamically render the item container based on the value of item in the loop. For example, when the value of item is "eat", I want to render the container with a border. I have tried to write it like this:

<template component>
    <h3>x-fill demo</h3>
    <div id="fill-container" style="padding: 16px; background-color: #eee">
        <x-fill name="fillTemplate" :value="list"></x-fill>
    </div>
    <template name="fillTemplate">
        <x-if :value="$data==='eat'">
            <div class="fill-item" style="margin: 10px; padding: 10px; border: green solid 1px">I am rendered because
                eat!! {{$data}}</div>
        </x-if>
        <x-else>
            <div class="fill-item" style="margin: 10px; padding: 10px; border: red solid 1px">
                {{ $data }}
            </div>
        </x-else>
    </template>

    <script>
        export const tag = "fill-demo";
        export const data = {
            list: ['eat', 'sleep', 'coding']
        };
    </script>
</template>

However, the rendered result on the webpage is not what I expected:
image

Templates for x-fill now support using the first element as a template, with a hint in the console that you can wrap it in a div. Something like the following, for example, should solve your problem:

<template component>
  <h3>x-fill demo</h3>
  <div id="fill-container" style="padding: 16px; background-color: #eee">
    <x-fill name="fillTemplate" :value="list"></x-fill>
  </div>
  <template name="fillTemplate">
    <div>
      <x-if :value="$data==='eat'">
        <div
          class="fill-item"
          style="margin: 10px; padding: 10px; border: green solid 1px"
        >
          I am rendered because eat!! {{$data}}
        </div>
      </x-if>
      <x-else>
        <div
          class="fill-item"
          style="margin: 10px; padding: 10px; border: red solid 1px"
        >
          {{ $data }}
        </div>
      </x-else>
    </div>
  </template>

  <script>
    export const tag = "fill-demo";
    export const data = {
      list: ["eat", "sleep", "coding"],
    };
  </script>
</template>

or

<template component>
  <style>
    :host {
      display: block;
    }
    .fill-item {
      margin: 10px;
      padding: 10px;
      border: red solid 1px;
    }
    .fill-item.eat {
      border: green solid 1px;
    }
  </style>
  <h3>x-fill demo</h3>
  <div id="fill-container" style="padding: 16px; background-color: #eee">
    <x-fill name="fillTemplate" :value="list"></x-fill>
  </div>
  <template name="fillTemplate">
    <div class="fill-item" class:eat="$data === 'eat'">
      {{$data === 'eat' ? 'I am rendered because eat!!' : $data}}
    </div>
  </template>

  <script>
    export const tag = "fill-demo";
    export const data = {
      list: ["eat", "sleep", "coding"],
    };
  </script>
</template>

Only the first child element inside the template will be used This is reasonable.