# Getting element content into a ViewModel variable

**URL:** <https://discourse.aurelia.io/t/getting-element-content-into-a-viewmodel-variable/398>\
**Category:** Best Practices\
**Created:** [November 16, 2017, 9:06pm UTC](https://discourse.aurelia.io/t/getting-element-content-into-a-viewmodel-variable/398 "2017-11-16T21:06:26Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![djedi](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/djedi/32/312_2.png) [@djedi](https://discourse.aurelia.io/u/djedi)\
**Post date:** [November 16, 2017, 9:06pm UTC](https://discourse.aurelia.io/t/getting-element-content-into-a-viewmodel-variable/398/1 "2017-11-16T21:06:26Z")

</div>

I’m posting this here because it took me a while to figure out how to do this and hopefully I’ll learn a better way of doing it.

I wanted to get a custom elements data that would get inserted into a `<slot></slot>` into a variable that I could play around with.

For example, we have a pattern library and we want to show code samples. I want a custom element where I can put sample code in side the custom element and have the component render the code, not the html.

In my first attempt I was able to get [something working](https://gist.run/?id=d0dbca6a333cc1004e3540c055a7997a) by modifying the content with the `@processContent` decorator.

But by getting the content into a variable that I could work with in my view model, I can do more with it, such toggle between rendering the code or rendering the html.

toggle-code.html:

```auto
<template>
    <span style="display: none"><slot></slot></span>
    
    <style>
      pre {
        background-color: #eee;
        border: 1px solid #999;
        padding: 3px 9px;
      }
    </style>
    
    <div style="${visible ? '' : 'display:none'}">
        <div style="${render ? 'display:none' : ''}">
            <pre><code class="language-markup" au-syntax textcontent.bind="code"></code></pre>
        </div>
        <div style="${render ? '' : 'display:none'}" innerhtml.bind="code"></div>
        <button click.delegate="renderCode()">Render</button>
    </div>
    <button click.delegate="toggleCodeBlock()">${visible ? 'Hide' : 'Show'} Code</button>
    <br><br>
</template>

```

toggle-code.js

```auto
import {processContent, child} from 'aurelia-framework';

@processContent((compiler, resources, node) => {
    const originalContent = node.innerHTML;
    
    node.innerHTML = `<hackity-hack style="display:none" data.bind='${JSON.stringify(originalContent)}'></hackity-hack>`;    
    
    return true;
})
export class toggleCode {
    @child('hackity-hack') hackData;
  
    attached() {
        this.visible = true;
        this.render = false;
        this.code = this.hackData.data.trim();
    }

    toggleCodeBlock() {
        this.visible = !this.visible;
    }
    
    renderCode() {
        this.render = !this.render;
    }
}

```

See this gist for example: [https://gist.run/?id=207296739baf5ad6948fbfc6167f1ad7](https://gist.run/?id=207296739baf5ad6948fbfc6167f1ad7)

I would love to get some extra eyeballs on this to see if this is the best way to go about it, or if there is an easier way to do it.

---

<div class="post-metadata">

**Author:** ![jeffgrann](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/jeffgrann/32/43_2.png) [@jeffgrann](https://discourse.aurelia.io/u/jeffgrann)\
**Post date:** [November 17, 2017, 5:09pm UTC](https://discourse.aurelia.io/t/getting-element-content-into-a-viewmodel-variable/398/2 "2017-11-17T17:09:34Z")

</div>

> [@djedi](#):
>
> I wanted to get a custom elements data that would get inserted into a \<slot\>\</slot\> into a variable that I could play around with.

Why not inject the element into your view-model class, and then grab its inner HTML?

```
import {inject} from 'aurelia-framework';

@inject(Element)
export class toggleCode {
    constructor(element) {
        this.innerHTML = element.innerHTML;
    }
}

```

And if you want to be sure Aurelia does not process the code inside the toggle-code element, just add a `@processContent(false)` decorator on the view-model class.

---

<div class="post-metadata">

**Author:** ![djedi](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/djedi/32/312_2.png) [@djedi](https://discourse.aurelia.io/u/djedi)\
**Post date:** [November 17, 2017, 5:55pm UTC](https://discourse.aurelia.io/t/getting-element-content-into-a-viewmodel-variable/398/3 "2017-11-17T17:55:13Z")

</div>

This is an interesting idea. I noticed that it wrapped the content with `<au-content>` I would just have to pull that out. Also, it seem to “fix” html for you. Like if I do a simple table with no `<tbody>` tag, it will throw the `<tbody>` tag in there for me.

> **[Bring your Gists to life with GistRun](https://gist.run/?id=c61ad6e68fae72005fec43743132b03d)**
>
> GistRun is a site for running, creating and updating GitHub Gists. With GistRun you can easily share Gists on StackOverflow.

---

<div class="post-metadata">

**Author:** ![jeffgrann](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/jeffgrann/32/43_2.png) [@jeffgrann](https://discourse.aurelia.io/u/jeffgrann)\
**Post date:** [November 17, 2017, 7:17pm UTC](https://discourse.aurelia.io/t/getting-element-content-into-a-viewmodel-variable/398/4 "2017-11-17T19:17:03Z")

</div>

If you add `@processContent(false)`, Aurelia does nothing with the HTML, so `<au-content>` won’t be added: [GistRun](https://gist.run/?id=d6e2543b40a1bf56dc69a3be173c5475)

---

<div class="post-metadata">

**Author:** ![djedi](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/djedi/32/312_2.png) [@djedi](https://discourse.aurelia.io/u/djedi)\
**Post date:** [November 17, 2017, 7:51pm UTC](https://discourse.aurelia.io/t/getting-element-content-into-a-viewmodel-variable/398/5 "2017-11-17T19:51:38Z")

</div>

I tried that earlier but then it rendered the html when I didn’t want it to.

 ![GistRun](https://canada1.discourse-cdn.com/flex027/uploads/aurelia/original/1X/39198c2551307b9083eee657d7ce25d21396807a.png)

---

<div class="post-metadata">

**Author:** ![CasiOo](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/casioo/32/276_2.png) [@CasiOo](https://discourse.aurelia.io/u/CasiOo)\
**Post date:** [November 17, 2017, 10:47pm UTC](https://discourse.aurelia.io/t/getting-element-content-into-a-viewmodel-variable/398/6 "2017-11-17T22:47:13Z")

</div>

Here’s another way of doing it. Pretty annoying having to replace the slot comment node.  
[https://gist.run/?id=36953664e4f241c5ce8e0c92d286d2af](https://gist.run/?id=36953664e4f241c5ce8e0c92d286d2af)

```auto
<template>
    
    <style>
      pre {
        background-color: #eee;
        border: 1px solid #999;
        padding: 3px 9px;
      }
    </style>
    
    <div show.bind="visible">
        <div show.bind="!render">
            <pre><code class="language-markup" au-syntax textcontent.bind="code"></code></pre>
        </div>
        <div ref="slotContainer" show.bind="render"><slot></slot></div>
        <button click.delegate="renderCode()">Render</button>
    </div>
    <button click.delegate="toggleCodeBlock()">${visible ? 'Hide' : 'Show'} Code</button>
    <br><br>
</template>

```

```auto
export class toggleCode {
  
    attached() {
        this.visible = true;
        this.render = false;
        this.code = this.slotContainer.innerHTML.replace('<!--slot-->', '');
    }

    toggleCodeBlock() {
        this.visible = !this.visible;
    }
    
    renderCode() {
        this.render = !this.render;
    }
}

```

---

<div class="post-metadata">

**Author:** ![djedi](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/djedi/32/312_2.png) [@djedi](https://discourse.aurelia.io/u/djedi)\
**Post date:** [November 18, 2017, 5:48pm UTC](https://discourse.aurelia.io/t/getting-element-content-into-a-viewmodel-variable/398/7 "2017-11-18T17:48:10Z")

</div>

Oh nice. This does seem a lot more simple. `slotContainer` - going to have to remember this one!

---

<div class="post-metadata">

**Author:** ![TonyLugg](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/tonylugg/32/307_2.png) [@TonyLugg](https://discourse.aurelia.io/u/TonyLugg)\
**Post date:** [November 18, 2017, 6:28pm UTC](https://discourse.aurelia.io/t/getting-element-content-into-a-viewmodel-variable/398/8 "2017-11-18T18:28:36Z")

</div>

I think it is the “ref” attribute that is key. You can reference any element using ref.

---

<div class="post-metadata">

**Author:** ![djedi](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/djedi/32/312_2.png) [@djedi](https://discourse.aurelia.io/u/djedi)\
**Post date:** [February 20, 2018, 4:27pm UTC](https://discourse.aurelia.io/t/getting-element-content-into-a-viewmodel-variable/398/9 "2018-02-20T16:27:06Z")

</div>

Well, I thought this would work, but the problem is my code sample has aurelia components. they get rendered into their html with this method. So the code samples don’t work.

---

<div class="post-metadata">

**Author:** ![djedi](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/djedi/32/312_2.png) [@djedi](https://discourse.aurelia.io/u/djedi)\
**Post date:** [February 20, 2018, 6:38pm UTC](https://discourse.aurelia.io/t/getting-element-content-into-a-viewmodel-variable/398/10 "2018-02-20T18:38:05Z")

</div>

I’ve come up with a solution that works for aurelia components and doesn’t modify the html:

my-code-sample.html

```auto
    <template>
        <span style="display: none"><slot></slot></span>
        
        <style>
          pre {
            background-color: #eee;
            border: 1px solid #999;
            padding: 3px 9px;
          }
        </style>
        
        <div>
            <div>
                <pre><code class="language-markup" au-syntax textcontent.bind="code"></code></pre>
            </div>
            <template replaceable part="rendered"></template>
        </div>

        <br><br>
    </template>

```

my-code-sample.js

```auto
    import {processContent, child} from 'aurelia-framework';

    @processContent((compiler, resources, node) => {
        const originalContent = node.innerHTML;
        const stringified = JSON.stringify(originalContent);
        
        node.innerHTML = `<code-sample data.bind='${stringified}'></code-sample>`; 
        node.innerHTML += `<template replace-part="rendered">${originalContent}</template>`;
        
        return true;
    })
    export class MyCodeSample {
        @child('code-sample') codeSample;
      
        attached() {
            this.code = this.codeSample.data;
        }
    }

```

> **[Bring your Gists to life with GistRun](https://gist.run/?id=d3c8b68f5cf4a015a5f0fa35e7d94de3)**
>
> GistRun is a site for running, creating and updating GitHub Gists. With GistRun you can easily share Gists on StackOverflow.
