Separating start and end tags for conditional rendering












1















<template>
<div>
<template v-if="isFieldsetElement">
<fieldset>
<legend>Label Here</legend>
</template>
<template v-else>
<label>Label Here</label>
</template>

<span> Description </span>
<img src="image.png" />
<div>more stuff here </div>

<template v-if="isFieldsetElement">
</fieldset>
</template>
</div>
</template>


I'm unable to do this tag separation. Basically I have a separate header and footer (for the lack of better word) but I can't do this in Vue like its possible in server-side generated markup.



Is there a workaround or a more elegant solution for this issue?










share|improve this question

























  • No, Vue works with a complete document model so you cannot put together elements by parts

    – Phil
    Nov 21 '18 at 23:46











  • @Phil yea but there must be some workaround for when you need to wrap tags around components? Its a pretty common scenario right?

    – 3zzy
    Nov 21 '18 at 23:46
















1















<template>
<div>
<template v-if="isFieldsetElement">
<fieldset>
<legend>Label Here</legend>
</template>
<template v-else>
<label>Label Here</label>
</template>

<span> Description </span>
<img src="image.png" />
<div>more stuff here </div>

<template v-if="isFieldsetElement">
</fieldset>
</template>
</div>
</template>


I'm unable to do this tag separation. Basically I have a separate header and footer (for the lack of better word) but I can't do this in Vue like its possible in server-side generated markup.



Is there a workaround or a more elegant solution for this issue?










share|improve this question

























  • No, Vue works with a complete document model so you cannot put together elements by parts

    – Phil
    Nov 21 '18 at 23:46











  • @Phil yea but there must be some workaround for when you need to wrap tags around components? Its a pretty common scenario right?

    – 3zzy
    Nov 21 '18 at 23:46














1












1








1








<template>
<div>
<template v-if="isFieldsetElement">
<fieldset>
<legend>Label Here</legend>
</template>
<template v-else>
<label>Label Here</label>
</template>

<span> Description </span>
<img src="image.png" />
<div>more stuff here </div>

<template v-if="isFieldsetElement">
</fieldset>
</template>
</div>
</template>


I'm unable to do this tag separation. Basically I have a separate header and footer (for the lack of better word) but I can't do this in Vue like its possible in server-side generated markup.



Is there a workaround or a more elegant solution for this issue?










share|improve this question
















<template>
<div>
<template v-if="isFieldsetElement">
<fieldset>
<legend>Label Here</legend>
</template>
<template v-else>
<label>Label Here</label>
</template>

<span> Description </span>
<img src="image.png" />
<div>more stuff here </div>

<template v-if="isFieldsetElement">
</fieldset>
</template>
</div>
</template>


I'm unable to do this tag separation. Basically I have a separate header and footer (for the lack of better word) but I can't do this in Vue like its possible in server-side generated markup.



Is there a workaround or a more elegant solution for this issue?







vue.js vuejs2 vue-component






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 22 '18 at 0:08









Phil

97.5k11140160




97.5k11140160










asked Nov 21 '18 at 23:40









3zzy3zzy

26.1k84227361




26.1k84227361













  • No, Vue works with a complete document model so you cannot put together elements by parts

    – Phil
    Nov 21 '18 at 23:46











  • @Phil yea but there must be some workaround for when you need to wrap tags around components? Its a pretty common scenario right?

    – 3zzy
    Nov 21 '18 at 23:46



















  • No, Vue works with a complete document model so you cannot put together elements by parts

    – Phil
    Nov 21 '18 at 23:46











  • @Phil yea but there must be some workaround for when you need to wrap tags around components? Its a pretty common scenario right?

    – 3zzy
    Nov 21 '18 at 23:46

















No, Vue works with a complete document model so you cannot put together elements by parts

– Phil
Nov 21 '18 at 23:46





No, Vue works with a complete document model so you cannot put together elements by parts

– Phil
Nov 21 '18 at 23:46













@Phil yea but there must be some workaround for when you need to wrap tags around components? Its a pretty common scenario right?

– 3zzy
Nov 21 '18 at 23:46





@Phil yea but there must be some workaround for when you need to wrap tags around components? Its a pretty common scenario right?

– 3zzy
Nov 21 '18 at 23:46












3 Answers
3






active

oldest

votes


















2














Using Dynamic Components:



<component :is="isFieldsetElement ? 'fieldset' : 'div'">
<component :is="isFieldsetElement ? 'legend' : 'label'">
<span> Description </span>
<img src="image.png" />
<div>more stuff here </div>
</component>
</component>





share|improve this answer



















  • 1





    That's very clever. Never thought to use dynamic components to render plain old HTML tags.

    – Phil
    Nov 22 '18 at 0:01





















1















I'm unable to do this tag separation




That's right because Vue works with a complete document model so you cannot put together elements by parts



I'd go with a custom wrapping component. Something like...



<template>
<div> <!-- single root element required -->
<fieldset v-if="wrap">
<legend>{{ label }}</legend>
<slot></slot>
</fieldset>
<template v-else>
<label>{{ label }}</label>
<slot></slot>
</template>
</div>
</tenmplate>

<script>
export default {
name: 'FieldWrapper',
props: {
wrap: Boolean,
label: String
}
}
</script>


and use it like



<FieldWrapper :wrap="isFieldsetElement" label="Label Here">
<span> Description </span>
<img src="image.png" />
<div>more stuff here </div>
</FieldWrapper>


There's a little repetition of the <slot> within the component but for your use-case, I'd say that's acceptable.



JSFiddle Demo






share|improve this answer

































    1














    The output for PHP is a string, so you can set it like '' + 'hello' + '', but for JS framework, them used HTMLElement, so you can't do same thing here. I think you need to get used to using the component, also PHP. Example:



    <?php
    class View() {
    public $header; public $footer; public $content;
    }
    $view = new View(); $view->header = 'Hello';...
    ?>
    <html>
    <body>
    <header>
    <?php echo $view->header?>
    </header>
    <div id="root">
    <?php echo $view->content?>
    </div>
    <footer>
    <?php echo $view->footer?>
    </footer>
    </body>
    </html>


    For above source, header, footer, content both mean one component, and the content usually has many child component.



    So, tag separation never a good solution, include PHP template.



    <template>
    <div>
    <template v-if="isFieldsetElement">
    <fieldset>
    <legend>Label Here</legend>
    <span> Description </span>
    <img src="image.png" />
    <div>more stuff here </div>
    </fieldset>
    </template>
    <template v-else>
    <label>Label Here</label>
    <span> Description </span>
    <img src="image.png" />
    <div>more stuff here </div>
    </template>
    </div>
    </template>


    or the other way same as your did in php:



    var app = new Vue({data:{html:'<div>Hello</div>'}});
    <template v-html="html"></template>





    share|improve this answer

























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53421978%2fseparating-start-and-end-tags-for-conditional-rendering%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      2














      Using Dynamic Components:



      <component :is="isFieldsetElement ? 'fieldset' : 'div'">
      <component :is="isFieldsetElement ? 'legend' : 'label'">
      <span> Description </span>
      <img src="image.png" />
      <div>more stuff here </div>
      </component>
      </component>





      share|improve this answer



















      • 1





        That's very clever. Never thought to use dynamic components to render plain old HTML tags.

        – Phil
        Nov 22 '18 at 0:01


















      2














      Using Dynamic Components:



      <component :is="isFieldsetElement ? 'fieldset' : 'div'">
      <component :is="isFieldsetElement ? 'legend' : 'label'">
      <span> Description </span>
      <img src="image.png" />
      <div>more stuff here </div>
      </component>
      </component>





      share|improve this answer



















      • 1





        That's very clever. Never thought to use dynamic components to render plain old HTML tags.

        – Phil
        Nov 22 '18 at 0:01
















      2












      2








      2







      Using Dynamic Components:



      <component :is="isFieldsetElement ? 'fieldset' : 'div'">
      <component :is="isFieldsetElement ? 'legend' : 'label'">
      <span> Description </span>
      <img src="image.png" />
      <div>more stuff here </div>
      </component>
      </component>





      share|improve this answer













      Using Dynamic Components:



      <component :is="isFieldsetElement ? 'fieldset' : 'div'">
      <component :is="isFieldsetElement ? 'legend' : 'label'">
      <span> Description </span>
      <img src="image.png" />
      <div>more stuff here </div>
      </component>
      </component>






      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Nov 22 '18 at 0:00









      3zzy3zzy

      26.1k84227361




      26.1k84227361








      • 1





        That's very clever. Never thought to use dynamic components to render plain old HTML tags.

        – Phil
        Nov 22 '18 at 0:01
















      • 1





        That's very clever. Never thought to use dynamic components to render plain old HTML tags.

        – Phil
        Nov 22 '18 at 0:01










      1




      1





      That's very clever. Never thought to use dynamic components to render plain old HTML tags.

      – Phil
      Nov 22 '18 at 0:01







      That's very clever. Never thought to use dynamic components to render plain old HTML tags.

      – Phil
      Nov 22 '18 at 0:01















      1















      I'm unable to do this tag separation




      That's right because Vue works with a complete document model so you cannot put together elements by parts



      I'd go with a custom wrapping component. Something like...



      <template>
      <div> <!-- single root element required -->
      <fieldset v-if="wrap">
      <legend>{{ label }}</legend>
      <slot></slot>
      </fieldset>
      <template v-else>
      <label>{{ label }}</label>
      <slot></slot>
      </template>
      </div>
      </tenmplate>

      <script>
      export default {
      name: 'FieldWrapper',
      props: {
      wrap: Boolean,
      label: String
      }
      }
      </script>


      and use it like



      <FieldWrapper :wrap="isFieldsetElement" label="Label Here">
      <span> Description </span>
      <img src="image.png" />
      <div>more stuff here </div>
      </FieldWrapper>


      There's a little repetition of the <slot> within the component but for your use-case, I'd say that's acceptable.



      JSFiddle Demo






      share|improve this answer






























        1















        I'm unable to do this tag separation




        That's right because Vue works with a complete document model so you cannot put together elements by parts



        I'd go with a custom wrapping component. Something like...



        <template>
        <div> <!-- single root element required -->
        <fieldset v-if="wrap">
        <legend>{{ label }}</legend>
        <slot></slot>
        </fieldset>
        <template v-else>
        <label>{{ label }}</label>
        <slot></slot>
        </template>
        </div>
        </tenmplate>

        <script>
        export default {
        name: 'FieldWrapper',
        props: {
        wrap: Boolean,
        label: String
        }
        }
        </script>


        and use it like



        <FieldWrapper :wrap="isFieldsetElement" label="Label Here">
        <span> Description </span>
        <img src="image.png" />
        <div>more stuff here </div>
        </FieldWrapper>


        There's a little repetition of the <slot> within the component but for your use-case, I'd say that's acceptable.



        JSFiddle Demo






        share|improve this answer




























          1












          1








          1








          I'm unable to do this tag separation




          That's right because Vue works with a complete document model so you cannot put together elements by parts



          I'd go with a custom wrapping component. Something like...



          <template>
          <div> <!-- single root element required -->
          <fieldset v-if="wrap">
          <legend>{{ label }}</legend>
          <slot></slot>
          </fieldset>
          <template v-else>
          <label>{{ label }}</label>
          <slot></slot>
          </template>
          </div>
          </tenmplate>

          <script>
          export default {
          name: 'FieldWrapper',
          props: {
          wrap: Boolean,
          label: String
          }
          }
          </script>


          and use it like



          <FieldWrapper :wrap="isFieldsetElement" label="Label Here">
          <span> Description </span>
          <img src="image.png" />
          <div>more stuff here </div>
          </FieldWrapper>


          There's a little repetition of the <slot> within the component but for your use-case, I'd say that's acceptable.



          JSFiddle Demo






          share|improve this answer
















          I'm unable to do this tag separation




          That's right because Vue works with a complete document model so you cannot put together elements by parts



          I'd go with a custom wrapping component. Something like...



          <template>
          <div> <!-- single root element required -->
          <fieldset v-if="wrap">
          <legend>{{ label }}</legend>
          <slot></slot>
          </fieldset>
          <template v-else>
          <label>{{ label }}</label>
          <slot></slot>
          </template>
          </div>
          </tenmplate>

          <script>
          export default {
          name: 'FieldWrapper',
          props: {
          wrap: Boolean,
          label: String
          }
          }
          </script>


          and use it like



          <FieldWrapper :wrap="isFieldsetElement" label="Label Here">
          <span> Description </span>
          <img src="image.png" />
          <div>more stuff here </div>
          </FieldWrapper>


          There's a little repetition of the <slot> within the component but for your use-case, I'd say that's acceptable.



          JSFiddle Demo







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 22 '18 at 0:00

























          answered Nov 21 '18 at 23:51









          PhilPhil

          97.5k11140160




          97.5k11140160























              1














              The output for PHP is a string, so you can set it like '' + 'hello' + '', but for JS framework, them used HTMLElement, so you can't do same thing here. I think you need to get used to using the component, also PHP. Example:



              <?php
              class View() {
              public $header; public $footer; public $content;
              }
              $view = new View(); $view->header = 'Hello';...
              ?>
              <html>
              <body>
              <header>
              <?php echo $view->header?>
              </header>
              <div id="root">
              <?php echo $view->content?>
              </div>
              <footer>
              <?php echo $view->footer?>
              </footer>
              </body>
              </html>


              For above source, header, footer, content both mean one component, and the content usually has many child component.



              So, tag separation never a good solution, include PHP template.



              <template>
              <div>
              <template v-if="isFieldsetElement">
              <fieldset>
              <legend>Label Here</legend>
              <span> Description </span>
              <img src="image.png" />
              <div>more stuff here </div>
              </fieldset>
              </template>
              <template v-else>
              <label>Label Here</label>
              <span> Description </span>
              <img src="image.png" />
              <div>more stuff here </div>
              </template>
              </div>
              </template>


              or the other way same as your did in php:



              var app = new Vue({data:{html:'<div>Hello</div>'}});
              <template v-html="html"></template>





              share|improve this answer






























                1














                The output for PHP is a string, so you can set it like '' + 'hello' + '', but for JS framework, them used HTMLElement, so you can't do same thing here. I think you need to get used to using the component, also PHP. Example:



                <?php
                class View() {
                public $header; public $footer; public $content;
                }
                $view = new View(); $view->header = 'Hello';...
                ?>
                <html>
                <body>
                <header>
                <?php echo $view->header?>
                </header>
                <div id="root">
                <?php echo $view->content?>
                </div>
                <footer>
                <?php echo $view->footer?>
                </footer>
                </body>
                </html>


                For above source, header, footer, content both mean one component, and the content usually has many child component.



                So, tag separation never a good solution, include PHP template.



                <template>
                <div>
                <template v-if="isFieldsetElement">
                <fieldset>
                <legend>Label Here</legend>
                <span> Description </span>
                <img src="image.png" />
                <div>more stuff here </div>
                </fieldset>
                </template>
                <template v-else>
                <label>Label Here</label>
                <span> Description </span>
                <img src="image.png" />
                <div>more stuff here </div>
                </template>
                </div>
                </template>


                or the other way same as your did in php:



                var app = new Vue({data:{html:'<div>Hello</div>'}});
                <template v-html="html"></template>





                share|improve this answer




























                  1












                  1








                  1







                  The output for PHP is a string, so you can set it like '' + 'hello' + '', but for JS framework, them used HTMLElement, so you can't do same thing here. I think you need to get used to using the component, also PHP. Example:



                  <?php
                  class View() {
                  public $header; public $footer; public $content;
                  }
                  $view = new View(); $view->header = 'Hello';...
                  ?>
                  <html>
                  <body>
                  <header>
                  <?php echo $view->header?>
                  </header>
                  <div id="root">
                  <?php echo $view->content?>
                  </div>
                  <footer>
                  <?php echo $view->footer?>
                  </footer>
                  </body>
                  </html>


                  For above source, header, footer, content both mean one component, and the content usually has many child component.



                  So, tag separation never a good solution, include PHP template.



                  <template>
                  <div>
                  <template v-if="isFieldsetElement">
                  <fieldset>
                  <legend>Label Here</legend>
                  <span> Description </span>
                  <img src="image.png" />
                  <div>more stuff here </div>
                  </fieldset>
                  </template>
                  <template v-else>
                  <label>Label Here</label>
                  <span> Description </span>
                  <img src="image.png" />
                  <div>more stuff here </div>
                  </template>
                  </div>
                  </template>


                  or the other way same as your did in php:



                  var app = new Vue({data:{html:'<div>Hello</div>'}});
                  <template v-html="html"></template>





                  share|improve this answer















                  The output for PHP is a string, so you can set it like '' + 'hello' + '', but for JS framework, them used HTMLElement, so you can't do same thing here. I think you need to get used to using the component, also PHP. Example:



                  <?php
                  class View() {
                  public $header; public $footer; public $content;
                  }
                  $view = new View(); $view->header = 'Hello';...
                  ?>
                  <html>
                  <body>
                  <header>
                  <?php echo $view->header?>
                  </header>
                  <div id="root">
                  <?php echo $view->content?>
                  </div>
                  <footer>
                  <?php echo $view->footer?>
                  </footer>
                  </body>
                  </html>


                  For above source, header, footer, content both mean one component, and the content usually has many child component.



                  So, tag separation never a good solution, include PHP template.



                  <template>
                  <div>
                  <template v-if="isFieldsetElement">
                  <fieldset>
                  <legend>Label Here</legend>
                  <span> Description </span>
                  <img src="image.png" />
                  <div>more stuff here </div>
                  </fieldset>
                  </template>
                  <template v-else>
                  <label>Label Here</label>
                  <span> Description </span>
                  <img src="image.png" />
                  <div>more stuff here </div>
                  </template>
                  </div>
                  </template>


                  or the other way same as your did in php:



                  var app = new Vue({data:{html:'<div>Hello</div>'}});
                  <template v-html="html"></template>






                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Nov 22 '18 at 0:03

























                  answered Nov 21 '18 at 23:57









                  Nick WangNick Wang

                  50925




                  50925






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53421978%2fseparating-start-and-end-tags-for-conditional-rendering%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

                      Alcedinidae

                      Origin of the phrase “under your belt”?