# Pseudo Inverted Templates Techniques

**URL:** <https://forums.bitovi.com/t/pseudo-inverted-templates-techniques/996>\
**Category:** DoneJS\
**Created:** [November 15, 2018, 3:32pm UTC](https://forums.bitovi.com/t/pseudo-inverted-templates-techniques/996 "2018-11-15T15:32:48Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![justinbmeyer](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.bitovi.com/justinbmeyer/32/179_2.png) [@justinbmeyer](https://forums.bitovi.com/u/justinbmeyer)\
**Post date:** [November 15, 2018, 3:32pm UTC](https://forums.bitovi.com/t/pseudo-inverted-templates-techniques/996/1 "2018-11-15T15:32:48Z")

</div>

[This thread started a discussion](https://gitter.im/donejs/donejs?at=5bed010692b7d117218f2e2b) of how to do inverted templates in donejs.

Inverted templates (I think they are [layouts in Ruby on Rails](https://guides.rubyonrails.org/layouts_and_rendering.html)) allow “child” components/views/etc to alter the structure of parent components/view/etc.

For example, we might have components for different parts of the page. A home, blog and product component. We’d like to build these components to include the view for the main content (`<article>`) of the page, the `<head>` element of the page, and perhaps even a sidebar `<nav>`.

The chat discusses a variety of ways to do it.

### Not doing it by having all the configuration in the appVM

```auto
<html>
  <head>{{content.head(this)}}</head>
  <body>{{content.body(this)}}</body>
</html>

```

```auto
  "404": {
    head: stache(`<title>404</title>`),
    body: stache(`<h1>uh oh</h1>`)
  },
  "200": {
    head: stache(`<title>My Cool Site</title>`),
    body: stache(`<h1>Hello World</h1>`)
   }
}

DefineMap.extend({
  get content(){
     if( IS_200 ) { return contents["200"] }
     else { return contents["400"] }
  }
})

```

Pros: simple  
Cons: doesn’t progressively load, components are not being used

### Add a `headView` to component’s prototype and read it:

All page components would look something like:

```auto
Component.extend({
  tag: "blog-page",
  view: `<articles> .... </articles>`,
  headView: stache(`<title>Blog</title>`),
  ViewModel: {...}
})

```

index.stache would call out to a `pageComponentHeadView` with the `pageComponentViewModel`:

```auto
<head>
  {{ pageComponentHeadView(pageComponentViewModel) }}
</head>
<body>
  {{pageComponentPromise.value}}
</body>

```

The appVM would get these properties:

```auto
get pageComponentPromise() {
  return steal.import( .... ).then(()=>{ new Component })
},
pageComponent: {
  get(lastValue, resolve){
    this.pageComponentPromise.then(resolve)
  } 
}
get pageComponentHeadView() { 
  return this.pageComponent && this.pageComponent.headView
},
get pageComponentViewModel() { 
  return this.pageComponent && this.pageComponent.viewModel
},

```

---

<div class="post-metadata">

**Author:** ![matthewp](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.bitovi.com/matthewp/32/77_2.png) [@matthewp](https://forums.bitovi.com/u/matthewp)\
**Post date:** [November 15, 2018, 6:15pm UTC](https://forums.bitovi.com/t/pseudo-inverted-templates-techniques/996/2 "2018-11-15T18:15:31Z")

</div>

We talked about this some more offline and came up with a few different ideas on how to solve this problem.

For those just now reading about this, the problem we are trying to solve is _projecting part of a template somewhere else_.

It’s best discussed with a common case. You have various page components in your app, and you want to modify the `<head>` depending on which page component you are showing. With done-autorender you can do this directly in the `index.stache` template but it becomes a bit repetitive.

```handlebars
<html>
<head>
  {{#eq(page, "cart")}}
    <title>Cart</title>
  {{/eq}}
  
  {{#eq(page, "home")}}
    <title>Home page</title>
  {{/eq}}
</head>
<body>
  {{#eq(page, "cart")}}
    <app-cart />
  {{/eq}}
  
  {{#eq(page, "home")}}
    <app-home />
  {{/eq}}
</body>
</html>

```

Notice that we have two of what are essentially the same chunks of code in both the head and the body. The **pageComponent** pattern cleans up the body part a bit. And you _could_ extend that pattern to also deal with the head. It does turn into configuration soup though.

What you _really_ want is to colocate the template that gets projected into the head with the rest of your component. Here’s a couple of different ideas that attempt to achieve that:

# Adding template to the component definition

Anything you put on the can-component definition should be available on the component’s prototype. For example if you were to do:

```auto
import { Component } from "can";

const Cart = Component.extend({
  tag: "app-cart",
  view: `
    <h1>Items: {{count}}</h1>
  `,
  
  headView: stache("<title>Cart</title>")
});

let cart = new Cart();

document.head.appendChild(cart.headView());

```

Notice that we are able to use `headView` as part of the component instance.

This means that when using the [pageComponent pattern](https://donejs.github.io/next/place-my-order.html#switch-between-components) you could do this in your index.stache:

```handlebars
<html>
<head>
  {{pageComponent.headView(pageComponent.viewModel)}}
</head>
<body>
  <h1>My app</h1>
  
  {{pageComponent}}
  
  <script src="./node_modules/steal/steal.js" main></script>
</body>
</html>

```

The important line here is `{{pageComponent.headView(pageComponent.viewModel)}}`. This calls the `headView` template, which again is just something on the component’s prototype, and passes in the viewModel as the scope.

## Making inline partials accessible from the outside

This is very similar to the first idea, but instead of having to define a separate template you can just do it as an inline partial For example your template might look like:

```auto
import { Component } from "can";

const Cart = Component.extend({
  tag: "app-cart",
  view: `
    {{<head}}
      <title>Cart</title>
    {{/head}}
  
    <h1>Items: {{count}}</h1>
  `
});

```

Notice we are using an inline partial named `head` here. Then to use it in your app you might do:

```handlebars
<html>
<head>
  {{pageComponent.view.head(pageComponent.viewModel)}}
</head>
<body>
  <h1>My app</h1>
  
  {{pageComponent}}
  
  <script src="./node_modules/steal/steal.js" main></script>
</body>
</html>

```

Again, this is very similar to the first idea. In this case the component instance’s `view` property gets a `head` property added to it, which is the inline partial. We call that as a function just like in the other example.

# Portals

This idea comes from other frameworks which have the idea of “portals”. A **portal** is a way to project part of your template to another DOM node. In stache this would likely be done using a new helper:

```auto
import { Component } from "can";

const Cart = Component.extend({
  tag: "app-cart",
  
  ViewModel: {
    head: () => document.head
  }
  
  view: `
    {{#portal(head)}}
      <title>Cart</title>
    {{/portal}}
  
    <h1>Items: {{count}}</h1>
  `
});

```

There are two parts to this worth pointing out. First there is the new `{{portal()}}` helper. You call this helper and pass in a DOM node that you would like the contents to be projected to. Here we are passing in the reference to `head`.

Since `head` is defined on our ViewModel to point to `document.head`, this means the contents of the portal would be rendered into the head.

You could imagine that this technique (as well as the previous ones) would be useful in other cases, like modals which you project somewhere else in the DOM than the component’s own children.

---

<div class="post-metadata">

**Author:** ![MarcGodard](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.bitovi.com/marcgodard/32/171_2.png) [@MarcGodard](https://forums.bitovi.com/u/MarcGodard)\
**Post date:** [November 15, 2018, 6:28pm UTC](https://forums.bitovi.com/t/pseudo-inverted-templates-techniques/996/3 "2018-11-15T18:28:24Z")

</div>

> [@matthewp](#):
>
> inline partials accessible from the outside

I can see something like this being useful for other things as well.

---

<div class="post-metadata">

**Author:** ![matthewp](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.bitovi.com/matthewp/32/77_2.png) [@matthewp](https://forums.bitovi.com/u/matthewp)\
**Post date:** [November 16, 2018, 4:31pm UTC](https://forums.bitovi.com/t/pseudo-inverted-templates-techniques/996/4 "2018-11-16T16:31:57Z")

</div>

I have a preference for the `{{#portal()}}` idea. I think it gives more control to the component that is rendering it.

For example, say you wanted to only update the head in a certain condition:

```handlebars
const NewOrder = Component.extend({
  tag: "order-new",
  
  ViewModel: {
    modalElement: {
      default: () => document.querySelector('.modal')
    }
  },
  
  view: `
    {{#if ( showModal ) }}

      {{# portal( modalElement ) }}
        <app-modal text="Close" />
      {{/ portal }}

    {{/ if }}
  
    <h1>Items: {{count}}</h1>
  `
});

```

Using one of the other methods we would _always_ be rendering the template within the projected element.

Another nice thing about `{{portal(el)}}` is that it makes it really easy to create wrappers. For example we could trivially create a `can-head` element or something:

```auto
Component.extend({
  tag: "new-order",

  view: `
    <can-head>
      <title>New Order</title>
    </can-head>
  `
});

```

Where `can-head` is essentially just:

```auto
Component.extend({
  tag: "can-head",
 
  ViewModel: {
    head: { default: () => document.head }
  }

  view: `{{#portal(head)}}<content />{{/portal}}`
});

```
