Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replaceable templates not working across multiple levels #625

Open
Mobe91 opened this issue Jun 13, 2018 · 10 comments
Open

Replaceable templates not working across multiple levels #625

Mobe91 opened this issue Jun 13, 2018 · 10 comments
Labels

Comments

@Mobe91
Copy link

Mobe91 commented Jun 13, 2018

Replaceable templates accross multiple levels as shown in the following sketch are not working. The replaceable template in tab.html gets replaced with empty content.

tab.html

<template>
  <div class="title">Tab-Title</div>
  <template replaceable part="tab1-content"></template>
</template>

tab-control.html

<template>
  <tab>
    <template replace-part="tab1-content">
      <template replaceable part="tab1"></template>
    </template>
  </tab>
</template>

app.html

<template>
  <tab-control>
    <template replace-part="tab1">
      <form>...</form>
    </template>
  </tab-control>
</template>

Neither works this:

tab.html

<template>
  <div class="title">Tab-Title</div>
  <template replaceable part="tab1-content"></template>
</template>

tab-control.html

<template>
  <tab>
    <template replaceable part="tab1"></template>
  </tab>
</template>

app.html

<template>
  <tab-control>
    <template replace-part="tab1">
      <template replace-part="tab1-content">
        <form>...</form>
      </template>
    </template>
  </tab-control>
</template>
@StrahilKazlachev
Copy link
Contributor

At the moment replaceable parts are single level.

@Mobe91
Copy link
Author

Mobe91 commented Jun 13, 2018

@StrahilKazlachev the first example is actually designed to be single level if the templates are replaced top-down.

@StrahilKazlachev
Copy link
Contributor

By single level I meant direct. In the first example you are targeting from App in <tab>, through <tab-control>. This just isn't supported.

@JoshMcCullough
Copy link

@bigopon
Copy link
Member

bigopon commented Feb 5, 2019

I'm uncertain whether we can support this feature. Consider the following example:

a.html

<template>
  <div replaceable part="part-1">
    <div replaceable part="part-1a">Part 1a</div>
    <div replaceable part="part-1b">Part 1b</div>
  </div>
  <div replaceable part="part-2">
    <div replaceable part="part-2a">Part 2a</div>
    <div replaceable part="part-2b">Part 2b</div>
  </div>
</template>

What we are seeing here is 2 levels deep replaceable templates, with part="part-1" and part="part-2"
Now suppose use this custom element in the following way:
app.html

<template>
  <a>
    <template replace-part="part-1">...</template>
  </a>
</template>

The moment we replace part="part-1" in a.html with <template replace-part="part-1">...</template> from app.html, we lose all information about the replaced destination, because the parent <template replaceable part="part-1"> is lost, thus all the children of it:

<div replaceable part="part-1"> <!-- if this is replaced -->
  <!-- all the following are gone, no trace of what to replace inside -->
  <div replaceable part="part-1a">Part 1a</div>
  <div replaceable part="part-1b">Part 1b</div>
</div>

This is like assigning a new object to a property, there is no way to know what old properties there were for reconciliation.

In case that we know all to-be-replaced parts of the destination, and all provided parts to replace them, what should be done with non-replaceable parts?

a.html

<template>
  <div replaceable part="part-1">
    <!-- what should be done for this -->
    <h1>Not replaceable 1</h1>
    <div replaceable part="part-1a">Part 1a</div>
    <div replaceable part="part-1b">Part 1b</div>
  </div>
  <div replaceable part="part-2">
    <!-- what should be done for this -->
    <h1>Not replaceable 2</h1>
    <div replaceable part="part-2a">Part 2a</div>
    <div replaceable part="part-2b">Part 2b</div>
  </div>
</template>

For the above template, maybe part-1, part-1a, part-1b, part-2, part-2a, part-2b can all be made to work, what can be done with the two <h1/> elements once we want to replace both part-x and part-xa, part-xb?

thoughts ? @Mobe91 @StrahilKazlachev @JoshMcCullough @fkleuver @EisenbergEffect

@fkleuver
Copy link
Member

fkleuver commented Feb 5, 2019

@bigopon If you add a (failing or passing) test for it in the vNext repo I can debug and see what might be needed to make it work, or establish whether it's possible at all (and give solid reasoning why not, if not).

@JoshMcCullough
Copy link

@bigopon If you have chosen to replace part-1, in your example, you have specifically chosen to "not care about and replace" the entire contents, including the other replaceable parts. IMO that is completely fine, and the correct result. If you intended to replace only the inner parts, you could have done that as well. This allows for the most flexibility.

Additionally, you added the <h1> which is "not replaceable" however, it is completely replaceable since it resides within a replaceable template. So it never was actually "not replaceable" in your example. The two <h1> elements should be replaced if the user is providing a replacement for the containing replaceable part.

@bigopon
Copy link
Member

bigopon commented Feb 5, 2019

@fkleuver @JoshMcCullough I would imagine something like this

foo.html

<template>
  <div replaceable part="part-1">
    <h1>Not replaceable 1</h1>
    <div replaceable part="part-1a">Part 1a</div>
    <div replaceable part="part-1b">Part 1b</div>
  </div>
  <div replaceable part="part-2">
    <h1>Not replaceable 2</h1>
    <div replaceable part="part-2a">Part 2a</div>
    <div replaceable part="part-2b">Part 2b</div>
  </div>
</template>

Case 1: I want to replace part-1 (or part-2, simplified to only part-1):

app.html

<a>
  <template replace-part="part-1">
    ... i don't care what is in side part-1 in the destination. this is gonna be the content
  </template>
</a>

Case 2: I want to replace part-1/part-1a:

<foo>
  <template replace-part="part-1/part-1a">
    ... i don't care what is inside part-1 in the destination.
    ... i don't care what is inside part-1a in the destination
    ... i don't care what is inside part-1b in the destination
    ... This is gonna be the content of part-1a in part-1
  </template>
</foo>

Case 2: I want to replace part-1/part-1a and part-1/part-1b:

<foo>
  <template replace-part="part-1/part-1a">
    ... i don't care what is inside part-1 in the destination.
    ... i don't care what is inside part-1a in the destination
    ... i don't care what is inside part-1b in the destination
    ... This is gonna be the content of part-1a in part-1
  </template>
  <template replace-part="part-1/part-1b">
    ... i don't care what is inside part-1 in the destination.
    ... i don't care what is inside part-1a in the destination
    ... i don't care what is inside part-1b in the destination
    ... This is gonna be the content of part-1b in part-1
  </template>
</foo>

Additionally, you added the <h1> which is "not replaceable" however, it is completely replaceable since it resides within a replaceable template. So it never was actually "not replaceable" in your example. The two <h1> elements should be replaced if the user is providing a replacement for the containing replaceable part.

@JoshMcCullough Yes, it was there to demonstrate that we can't conditionally pick what to be replaced, when we provide both parent-replaceable and child-replaceable.

@JoshMcCullough
Copy link

JoshMcCullough commented Feb 6, 2019

So I wouldn't think you'd use replace-part="part-1/part-1a", but rather simply replace-part="part-1a.

I think all of your examples are correct in your latest comment. And it's up to the user to decide if they are replacing the outer or inner parts in this case. Aurelia could potentially raise an error/warning if a user tried to do this )using your example) ...

<!-- example to cause an error -->
<foo>
  <template replace-part="part-1">
    ...new content for part 1
  </template>

  <template replace-part="part-1a">
    ...new content for part 1a
  </template>
</foo>

ERROR: Cannot replace both parts "part-1" and "part-1a", one is nested within the other.

@Mobe91
Copy link
Author

Mobe91 commented Feb 6, 2019

@bigopon With regard to your example I would expect this to behave like @JoshMcCullough described.

But I don't see how your example relates to my original one because you don't really have nested templates but rather just nested replacement points within a single template..

While I understand that multi-level replacement is not supported right now I feel that it should be possible to support it by just processing the replacement points top-to-bottom and by reprocessing each intermediate replacement result. When I apply such an algorithm to version 1 of my original example, I end up with the correct end result:

  1. Process app.html
  2. Instantiate the tab-control template which yields a logical intermediate view of
<template>
  <tab-control>
    <tab>
      <template replace-part="tab1-content">
        <template replaceable part="tab1"></template>
      </template>
    </tab>
  </tab-control>
</template>
  1. Apply replacements for part tab1 defined in app.html which yields
<template>
  <tab-control>
    <tab>
      <template replace-part="tab1-content">
        <form>...</form>
      </template>
    </tab>
  </tab-control>
</template>
  1. Now we need to instantiate and replace again - instantiate tab with result
<template>
  <tab-control>
    <tab>
      <div class="title">Tab-Title</div>
      <template replaceable part="tab1-content"></template>
    </tab>
  </tab-control>
</template>
  1. Apply replacements for part tab1-content defined in the intermediate result of step 3 which yields the expected end result
<template>
  <tab-control>
    <tab>
      <div class="title">Tab-Title</div>
      <form>...</form>
    </tab>
  </tab-control>
</template>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants