# Color Chooser Illustrates ViewModel Hierarchy Questions

**URL:** <https://forums.bitovi.com/t/color-chooser-illustrates-viewmodel-hierarchy-questions/938>\
**Category:** CanJS\
**Created:** [July 27, 2018, 7:46pm UTC](https://forums.bitovi.com/t/color-chooser-illustrates-viewmodel-hierarchy-questions/938 "2018-07-27T19:46:05Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![code-read](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.bitovi.com/code-read/32/111_2.png) [@code-read](https://forums.bitovi.com/u/code-read)\
**Post date:** [July 27, 2018, 7:46pm UTC](https://forums.bitovi.com/t/color-chooser-illustrates-viewmodel-hierarchy-questions/938/1 "2018-07-27T19:46:05Z")

</div>

In [Communication between "sibling" ViewModels - #6 by code-read](https://forums.bitovi.com/t/communication-between-sibling-viewmodels/927/6), I said:

> Conceptually, I’m attempting to 1) build a series of similar HTML elements in a loop; and 2) listen and respond to changes and/or events occurring on each one separately.

I’ve since coded a [CanJS color chooser](http://colors.code-read.com), my first framework-based web project. It attempts to accomplish the above, but I have some questions about my design. In particular:

1. Do I rely too heavily on **_global variables_** to share information between ViewModels?

2. Can I create a `<final-el>` VM to manage color cell properties **_individually_** rather than relying on indexes in their element ID’s? (for details see `todo: <final-el>` in the project’s [index.html file](https://github.com/CODE-REaD/CanJS-ColorChooser/blob/master/index.html)).

3. I want to play a sound effect when the user hovers over a grid cell, but the sound lags so far behind the visual display as to degrade rather than improve UX (see `todo: address lag` in [index.html](https://github.com/CODE-REaD/CanJS-ColorChooser/blob/master/index.html)). Is there a better way?

The full source code is [posted on GitHub](https://github.com/CODE-REaD/CanJS-ColorChooser). Thanks In Advance for your constructive criticism!

---

<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:** [July 27, 2018, 10:35pm UTC](https://forums.bitovi.com/t/color-chooser-illustrates-viewmodel-hierarchy-questions/938/2 "2018-07-27T22:35:01Z")

</div>

1. Instead of using globals, can you have them passed down from parent component to child component?

2. Yeah, that seems odd. Btw, you can link to line numbers in github. For example: [https://github.com/CODE-REaD/CanJS-ColorChooser/blob/master/index.html#L332](https://github.com/CODE-REaD/CanJS-ColorChooser/blob/master/index.html#L332) . This will make it far easier to know which code you are talking about. Why are you relying on indexes? I’ve never had to do this in CanJS.

3. You probably need to pre-load the sound source. I don’t know how, but I bet there’s a good way.

---

<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:** [July 27, 2018, 10:38pm UTC](https://forums.bitovi.com/t/color-chooser-illustrates-viewmodel-hierarchy-questions/938/3 "2018-07-27T22:38:21Z")

</div>

If you are building elements in a loop, can you use `{{#each }}`?

```auto
Component.extend({
  tag: "my-app",
  view: `{{#each colors}}<color-block color:from="this"/>{{/each}}`
  ViewModel: {
    colors: {
      default: (){
        return [{name: "black", value: "#000"}, ....]
      }
    }
  }
})

```

---

<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:** [July 27, 2018, 10:38pm UTC](https://forums.bitovi.com/t/color-chooser-illustrates-viewmodel-hierarchy-questions/938/4 "2018-07-27T22:38:53Z")

</div>

this is a sweet example btw!

---

<div class="post-metadata">

**Author:** ![code-read](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.bitovi.com/code-read/32/111_2.png) [@code-read](https://forums.bitovi.com/u/code-read)\
**Post date:** [July 29, 2018, 9:41pm UTC](https://forums.bitovi.com/t/color-chooser-illustrates-viewmodel-hierarchy-questions/938/5 "2018-07-29T21:41:25Z")

</div>

@justinbmeyer, thank you for [your comments](https://forums.bitovi.com/t/color-chooser-illustrates-viewmodel-hierarchy-questions/938/2?u=code-read)! My remarks on them:

1. When I try to configure the several VM’s under a common ‘parent’, I seem to lose the ability to derive the grid sizes from CSS as in [https://github.com/CODE-REaD/CanJS-ColorChooser/blob/master/index.html#L242](https://github.com/CODE-REaD/CanJS-ColorChooser/blob/master/index.html#L242) and [https://github.com/CODE-REaD/CanJS-ColorChooser/blob/master/index.html#L321](https://github.com/CODE-REaD/CanJS-ColorChooser/blob/master/index.html#L321) because I can no longer call window.getComputedStyle() since the target of that call is contained in the parent VM.

2. What I mean by “indexes” is, I’m storing each cell’s RGB values in its element ID and then parsing that to find its RGB value (see [https://github.com/CODE-REaD/CanJS-ColorChooser/blob/master/index.html#L292](https://github.com/CODE-REaD/CanJS-ColorChooser/blob/master/index.html#L292)). Then to change things in a single cell I have to send its x,y location to the VM (because the VM is working at the element’s “parent” level). If I could manage properties with an individual cell’s ViewModel, I would be able to store and retrieve these values directly as VM properties.

I would love to be enlightened on any of this.😄

---

<div class="post-metadata">

**Author:** ![code-read](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.bitovi.com/code-read/32/111_2.png) [@code-read](https://forums.bitovi.com/u/code-read)\
**Post date:** [July 29, 2018, 9:47pm UTC](https://forums.bitovi.com/t/color-chooser-illustrates-viewmodel-hierarchy-questions/938/6 "2018-07-29T21:47:39Z")

</div>

@justinbmeyer, in response to [your answer](https://forums.bitovi.com/t/color-chooser-illustrates-viewmodel-hierarchy-questions/938/3?u=code-read) about using `{{#each}}`, I tried that and it works, but the ViewModel still operates on the parent tag level. E.g., the following sets the content of all elements at once to “Received a mouseover”. Is this what you had in mind?

```
Component.extend({
    tag: "my-app",
    view: `
{{#each colors}}
    <my-el style="font-family:{{fontname}}; background-color:{{name}}">{{fontname}},{{tagText}}:{{value}}<br></my-el>
{{/each}}`,
    ViewModel: {
        colors: {
            default: function () {
                return [
                    {name: "white", value: "#fff"},
                    {name: "red", value: "#f00"},
                    {name: "green", value: "#0f0"},
                    {name: "blue", value: "#00f"},
                ];
            }
        },
        tagText: {default: "Here is my default text."}
    },
    events: {
        mouseover: function () {
            this.viewModel.tagText = "Received a mouseover.";
        },
    },
});
```

---

<div class="post-metadata">

**Author:** ![code-read](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.bitovi.com/code-read/32/111_2.png) [@code-read](https://forums.bitovi.com/u/code-read)\
**Post date:** [September 27, 2018, 9:45pm UTC](https://forums.bitovi.com/t/color-chooser-illustrates-viewmodel-hierarchy-questions/938/8 "2018-09-27T21:45:59Z")

</div>

As an exercise in comparison, I’ve created the same Color Chooser web app as the one referred to above, this time using Vue (code at [https://github.com/CODE-REaD/VueColorChooser/blob/master/index.html](https://github.com/CODE-REaD/VueColorChooser/blob/master/index.html) and working site at [http://vue-colors.code-read.com/;](http://vue-colors.code-read.com/;) code for CanJS version at [https://github.com/CODE-REaD/CanJS-ColorChooser/blob/master/index.html](https://github.com/CODE-REaD/CanJS-ColorChooser/blob/master/index.html) and working site at [http://colors.code-read.com](http://colors.code-read.com))

**I’m adding this post in hopes of gleaning your thoughts on this comparison.**

I initially tried to port the code as intact as possible from CanJS to Vue. As you can see, I was not successful. I believe the two frameworks each require their own ideom. My initial observations:

- The Vue Chooser’s code is about 10% shorter (excluding identical CSS sections). Should it be?;

- The Vue Chooser embeds **_way_** more logic in `<body>` and in HTML generally than the CanJS one;

- The CanJS Chooser relies much more heavily on custom elements than the Vue Chooser (should it?).

Questions:

- Did I approach the CanJS version’s design properly / ideomatically?

- Is CanJS overkill / Vue more appropriate for this type of limited app?

- Do you notice ways I might have condensed the CanJS code (while keeping it legible)?

_Thanks for your interest._

---

<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:** [September 28, 2018, 12:20am UTC](https://forums.bitovi.com/t/color-chooser-illustrates-viewmodel-hierarchy-questions/938/9 "2018-09-28T00:20:33Z")

</div>

I guess the biggest difference is that you broke CanJS into multiple components. I think if the 10% difference has you worried, I would just do everything in one component.

Also, I remember asking this, but I don’t remember why the code is generating stache like this:

```auto
    let finalItems = "";
    for (let i = 0; i < finalCols; i++) {
        for (let j = 0; j < finalCols; j++) {
            finalItems += `<final-el id="${i}.${j}" `
                + `class="{{isSelected(${i}.${j})}}" `
                + `style="color: {{cellFgColor(${i},${j})}}; background-color: rgb({{cellBgColor('Red',${i},${j})}},{{cellBgColor('Grn',${i},${j})}},{{cellBgColor('Blu',${i},${j})}})">`
                + `R:{{cellBgColor('Red',${i},${j})}}<br>G:{{cellBgColor('Grn',${i},${j})}}<br>B:{{cellBgColor('Blu',${i},${j})}}</final-el>`;
        }
    }

```

One final thing, why are you adding template literals like:

```auto
`<span style="text-align: right; padding: 6px"><b>Final<br>Color:</b></span>`
        + `<span style="color: {{textColor}}; padding: 12px; border: 3px solid gray; background-color: `
        + `rgb({{readoutRed}}, {{readoutGrn}}, {{readoutBlu}}); ">`
        + `R:{{readoutRed}}<br>G:{{readoutGrn}}<br>B:{{readoutBlu}}</span>`
        + `<span style="padding: 12px">{{#if(clipCopied)}}<b>{{clipCopied}}</b> copied to clipboard.{{/if}}</span>`
        + `<span></span>`
        + `<button on:click="copyToClip('{{readoutRGB}}')">Copy <b>{{readoutRGB}}</b> to clipboard</button>`
        + `<button on:click="copyToClip('{{readoutHex}}')">Copy <b>{{readoutHex}}</b> to clipboard</button>`,

```

Instead of just doing:

```auto
`<span style="text-align: right; padding: 6px"><b>Final<br>Color:</b></span>
 <span style="color: {{textColor}}; padding: 12px; border: 3px solid gray; background-color: 
 ... `

```

Template literals span multiple lines.

---

<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:** [September 28, 2018, 12:22am UTC](https://forums.bitovi.com/t/color-chooser-illustrates-viewmodel-hierarchy-questions/938/10 "2018-09-28T00:22:26Z")

</div>

If you could record a 5 min video of you showing off the functionality, I’ll create a demo.

---

<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:** [September 28, 2018, 1:31am UTC](https://forums.bitovi.com/t/color-chooser-illustrates-viewmodel-hierarchy-questions/938/11 "2018-09-28T01:31:33Z")

</div>

Oh

# DAMN!!!

Carson … How dare you bring in that weak as VUE shit. Now you know it

# is on!!!

Look what you made me do! I built a prototype of your color picker in 125 lines of code:

https://codepen.io/justinbmeyer/embed/preview/XPQoZd?height=300&slug-hash=XPQoZd&default-tabs=js,result&host=https://codepen.io&embed-version=2

# 😀

The prototype is fairly close in functionality to what you built. I didn’t make it perfect (no copy to clipboard). But hopefully you can see how it’s made.

Want to present this at a DoneJS Chicago?

---

<div class="post-metadata">

**Author:** ![code-read](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.bitovi.com/code-read/32/111_2.png) [@code-read](https://forums.bitovi.com/u/code-read)\
**Post date:** [October 1, 2018, 1:50pm UTC](https://forums.bitovi.com/t/color-chooser-illustrates-viewmodel-hierarchy-questions/938/12 "2018-10-01T13:50:53Z")

</div>

Thank you, @justinbmeyer. To answer your question, I would be honored to present this Color Picker at DoneJS Chicago.

As you can tell from prior messages, I’ve been struggling with CanJS `view` inheritance. My concern was to avoid iterating through the entire `<ul>` every time a `<li>` event occurred. I kept trying to manage click and hover events at the `<li>` level, but it seems a CanJS-coded event handler only operates at its `view` level.

Perhaps I have stumbled upon the purpose of the _virtual DOM_: my code need not manage DOM event listeners but rather should rely on CanJS to intelligently update them. _Am I on the right track?_

* * *

**Another issue:** each element in your `<ul class=final-colors>` appears in Chrome DevTools’ _Elements_ panel as:

`<li on:click="selectFinalColor(color)"...>`

yet is sending your `selectFinalColor(color)` method color values _ **specific to that `<li>`** _.

How this works is far from obvious. In pure JavaScript it simply fails and a function called via `onclick` generates an `Uncaught ReferenceError: color is not defined`. I’m assuming this is because parameters to `onclick` must be values, not references.

Adding a `debugger` statement to your `selectFinalColor(color)` method causes DevTools to reveal in its _Sources_ panel that in your Color Picker, `color` is an _object_ enclosing a property for each of the `<li>`'s three colors.

**_I didn’t expect that_** and am beginning to understand how much CanJS does “behind the scenes.” Apparently once we create an object (`color` here), it can be passed back and forth between `view`s and methods, and even revised “declaratively” by changing one of its dependencies (which you’ve stacked up here as `this.baseColor || this.suggestedBaseColor || this.lastBaseColor`) and CanJS synchronizes all side effects for me.

If the above is correct, **_I’m impressed by the power of it_** , but also concerned: how do I predict what CanJS will and will not manage “behind the scenes?” How is this object-passing capability described formally?

Example taken. Pointers appreciated.

* * *

**Addendum:**  
Dear @justinbmeyer, I cannot help but notice a **_performance problem_** with **[your example](http://canjs-colors.code-read.com/)**. When dragging my mouse back and forth over the top row of colors (`<ul class ='base-colors'`), updates to the `final-colors` grid are notably slow. Chrome DevTools attributes this _jank_ to _Scripting_:  
 ![image](https://canada1.discourse-cdn.com/flex035/uploads/donejs/original/1X/2289452465cb657e881b29dd028bb524056116f6.png)  
There are also complaints in Chrome’s console:  
`19:47:58.043 core.js:18161 [Violation] 'mouseenter' handler took 237ms`  
`19:47:58.307 core.js:18161 [Violation] 'mouseenter' handler took 226ms`  
`...`

The same test with [http://vue-colors.code-read.com/](http://vue-colors.code-read.com/) shows no such jank or console “Violations” and its performance report looks like:  
 ![image](https://canada1.discourse-cdn.com/flex035/uploads/donejs/original/1X/a7c5f0e5efb69853ed0cd815bec54175f00b1def.png)

Even [my CanJS example](http://colors.code-read.com/) runs much more smoothly.

Frankly, I’m stumped as to what is causing this. I found using `//unpkg.com/can/core.min.mjs` increased performance of your code significantly but still not on par with the other examples above. This is **_not_** what I expected. Why does my amateur code (and even my evil Vue script) outperform your far more elegant example?
