Improve the error message when `this` is undefined
If you try to use this within methods called by {{on}} and {{fn}}, they show a helpful error instructing the developer to use the @action decorator. The render modifiers could show something like that too.
Here's an example "error" use case for did-insert:
<div class="my-container" {{did-insert this.renderEditor}}></div>
import Component from '@glimmer/component';
export default class CodeEditor extends Component {
renderEditor(el) {
console.log(this.args.code)
}
}
TypeError: this is undefined
{{fn}} uses this error message:
You accessed
this.arg2from a function passed to thefnhelper, but the function itself was not bound to a validthiscontext. Consider updating to usage of@action.
cc @rwjblue this was opened at your suggestion following some chat in octane-migration.
Hey all. Just came upon this today. Is there a more proper way to access this inside of a component?
// component.hbs
<Input @type="text" @value={{@token}} {{did-insert this.verifyToken @token}}/>
// component.js
verifyToken(token) {
console.log(this) // logs 'undefined'
}
Am I misinterpreting how this addon should be used?
@ELepolt You have to use the @action decorator for your this.verifyToken function in the component class or else this === undefined
Example
@action
verifyToken(token) {
console.log(this) //Works
} ```
#OctaneWoes. Thank you so much.
One thing that I've learned here that someone can make use of is this.set() a value. Even with @action I've got an error: TypeError: this.set is not a function.
In my case, I had to save a reference to a node and solved that by using set from @ember/object:
{{!-- template.hbs --}}
<div {{did-insert this.setFileRef}}>
<div id="selector"></div>
</div>
// component.js
import Component from '@glimmer/component';
- import { action } from '@ember/object';
+ import { action, set } from '@ember/object';
export default class SomeComponent extends Component {
@action
setFileRef() {
- this.set('fieldRef', document.querySelector('#selector'));
+ set(this, 'fieldRef', document.querySelector('#selector'));
}
}
That might not be the best example because in this case {{ref}} in nicer. But I'll leave it here anyway.
@tniezurawski You don't need to use set in a glimmer component, in fact it's not recommended.
Also, you can do this code differently here. As a modifier passes in the element it's attached to so instead of looking through the whole document you can look just within this component.
@action
setFileRef(element) {
this.fieldRef = element.querySelector('#selector'));
}
@dgavey Oh, nice! Thanks for the explanation!
Anyone have a hint on where I could go about adding this ? Maybe here? https://github.com/emberjs/ember-render-modifiers/blob/master/addon/modifiers/did-insert.js#L61 How could I check that it's an action and not a regular function?