Skip to content

Instantly share code, notes, and snippets.

@jacobq
Last active April 28, 2022 21:58
Show Gist options
  • Save jacobq/4ca41970bae4e2a340929fd4366e8a1a to your computer and use it in GitHub Desktop.
Save jacobq/4ca41970bae4e2a340929fd4366e8a1a to your computer and use it in GitHub Desktop.
Nested tracking
import { tracked } from '@glimmer/tracking';
import Controller from '@ember/controller';
import { action } from '@ember/object';
import { VERSION } from '@ember/version';
import { later } from '@ember/runloop';
// Can't use this in Ember Twiddle yet because it
// needs to build with Embroider
// See https://github.com/ember-cli/ember-twiddle/issues/732
//import { deepTracked } from 'ember-deep-tracked';
class NumberContainer {
@tracked x;
y = new (class {
@tracked a = 0;
});
@tracked z = new (class {
@tracked b = 0;
});
// This works too
onlyChild = {
@tracked x: 0
};
// won't work natively (without .set())
@tracked foo = {
bar: 0
};
baz = {
quux: 0
};
constructor({x, y, z}) {
this.x = x;
this.y.a = y;
this.z.b = z;
}
}
export default class ApplicationController extends Controller {
appName = 'Ember Twiddle';
@tracked emberVersion = VERSION;
@tracked isIntervalTimerRunning = false;
@tracked updateCount = 0;
@tracked simpleStringMember = "test";
@tracked shallow = {
untracked: 1
};
@tracked container = new NumberContainer({
x: 1,
y: 0
});
/*
@deepTracked deep = {
foo: {
bar: {
a: [1, 2, 3],
},
baz: 456,
},
};
*/
deep = {
foo: {
bar: {
@tracked a: [1, 2, 3],
},
@tracked baz: 456,
},
};
updateIntervalMs = 500;
onTimer() {
if (!this.isIntervalTimerRunning) {
return;
}
this.simpleStringMember = Math.random().toString(16).substr(2, 8);
// Error: Assertion Failed...being tracked by a tracking context
//this.shallow.untracked += 1;
this.set('shallow.untracked', this.shallow.untracked + 1);
this.container.x *= 2;
this.container.y.a += 1;
this.container.z.b = this.simpleStringMember;
// These will fail if template references them
//this.container.foo.bar = Math.random();
//this.container.baz.quux = Math.random();
this.set('container.foo.bar', Math.random());
this.set('container.baz.quux', Math.random());
this.container.onlyChild.x = Math.random();
// Doesn't work without @deepTracked
this.deep.foo.bar.a.forEach((_x, i, array) => {
array[i] = Math.floor(100*Math.random());
})
// even if we do this
//this.notifyPropertyChange('deep.foo.bar.a');
this.deep.foo.baz = Math.floor(1000*Math.random());
this.updateCount += 1;
later(this, this.onTimer, this.updateIntervalMs);
}
@action
toggleTimer() {
console.log('toggleTimer');
this.isIntervalTimerRunning = !this.isIntervalTimerRunning;
if (this.isIntervalTimerRunning) {
this.onTimer(); // yes, it might call it an extra time
}
}
constructor(...args) {
super(...args);
this.isIntervalTimerRunning = true;
this.onTimer();
}
}
<h1>Welcome to {{this.appName}}</h1>
<h2>Using Ember v{{emberVersion}}</h2>
<button role="button" {{on "click" this.toggleTimer}}>{{if this.isIntervalTimerRunning "Stop" "Start"}} Timer</button><br>
<br>
simpleStringMember={{this.simpleStringMember}}<br>
<br>
shallow.untracked={{this.shallow.untracked}}<br>
<br>
deep.foo.bar.a={{this.deep.foo.bar.a}}<br>
deep.foo.bar.a[0]={{get this.deep.foo.bar "a.0"}}<br>
deep.foo.baz={{this.deep.foo.baz}}<br>
<br>
container.x={{this.container.x}}<br>
container.y.a={{this.container.y.a}}<br>
container.z.b={{this.container.z.b}}<br>
<br>
container.foo.bar={{this.container.foo.bar}}<br>
container.baz.quux={{this.container.baz.quux}}<br>
<br>
container.onlyChild.x={{this.container.onlyChild.x}}<br>
<br>
updateCount={{this.updateCount}}<br>
{{outlet}}
<br>
<br>
import Application from '../app';
import config from '../config/environment';
import { setApplication } from '@ember/test-helpers';
import { assign } from '@ember/polyfills';
import { start } from 'ember-qunit';
let attributes = {
rootElement: '#test-root',
autoboot: false
};
attributes = assign(attributes, config.APP);
let application = Application.create(attributes);
setApplication(application);
start();
{
"version": "0.17.1",
"EmberENV": {
"FEATURES": {},
"_TEMPLATE_ONLY_GLIMMER_COMPONENTS": false,
"_APPLICATION_TEMPLATE_WRAPPER": true,
"_JQUERY_INTEGRATION": true
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.js",
"ember": "3.18.1",
"ember-template-compiler": "3.18.1",
"ember-testing": "3.18.1",
"ember-cli-htmlbars": "5.7.1"
},
"addons": {
"@glimmer/component": "1.0.0"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment