emberjs / ember-render-modifiers Goto Github PK
View Code? Open in Web Editor NEWImplements did-insert / did-update / will-destroy modifiers for emberjs/rfcs#415
License: MIT License
Implements did-insert / did-update / will-destroy modifiers for emberjs/rfcs#415
License: MIT License
I'm not sure how/if this is really related to the modifiers, but I haven't been able to reproduce it without them. I believe it's some kind of interaction between babel/decorators/modifiers.
Apparently if in the callback passed to {{will-destroy}}
I use the global document
without having referenced it elsewhere, the compilation blows badly:
ReferenceError: document is not defined
at BasicDropdownTrigger.removeGlobalHandlers (/var/folders/bt/62lj_mr106zbk82m8kl772b00000gn/T/broccoli-9932Xc3l4ZKiotlD/out-271-broccoli_merge_trees/assets/addon-tree-output/ember-basic-dropdown/components/basic-dropdown-trigger.js:140:1)
at Object.destroyModifier (/var/folders/bt/62lj_mr106zbk82m8kl772b00000gn/T/broccoli-9932Xc3l4ZKiotlD/out-271-broccoli_merge_trees/assets/addon-tree-output/@ember/render-modifiers/modifiers/will-destroy.js:26:1)
at CustomModifierState.destroy (/var/folders/bt/62lj_mr106zbk82m8kl772b00000gn/T/broccoli-9932Xc3l4ZKiotlD/out-271-broccoli_merge_trees/assets/vendor/ember-modifier-manager-polyfill.js:58:1)
at SimpleBlockTracker.destroy (/var/folders/bt/62lj_mr106zbk82m8kl772b00000gn/T/broccoli-9932Xc3l4ZKiotlD/out-271-broccoli_merge_trees/assets/@glimmer/runtime.js:2411:1)
at UpdatableBlockTracker.destroy (/var/folders/bt/62lj_mr106zbk82m8kl772b00000gn/T/broccoli-9932Xc3l4ZKiotlD/out-271-broccoli_merge_trees/assets/@glimmer/runtime.js:2411:1)
The reproduction can be this PR: cibernox/ember-basic-dropdown#449
If (this line)[https://github.com/cibernox/ember-basic-dropdown/pull/449/files#diff-e8b1232b23cd9aba9a4b4c3f74b118fcR18] referencing the global document is removed the code fails to compile.
Since (to my knowledge) its not possible to conditionally add a modifier. Something like this:
then maybe the modifiers provided by this library could silently handle undefined functions, so you could do:
and when @onInsert
is undefined
it wont throw an error, like it does now.
Either make the current modifiers silently handle undefined
or make new ones to handle modifier function that might no always be provided. This is mostly for general components.
Another option might be to provide -if
version of the modifiers:
Hi, I'm having some issues with the helpers when using the latest version (2.0.4
) with Ember version 4.4.0
. Using did-insert
in a template triggers the following: Error: Invalid modifier manager compatibility specified
.
Hello!
Say I have a component Test
:
components/test/template.hbs
<div {{did-insert (fn (mut this.element))}} {{will-destroy (fn (mut this.element) null)}} />
When that component is destroyed, it results in the following error:
You modified "element" twice on [object Object] in a single render. It was rendered in undefined and modified in undefined. [...]
If I instead perform the registering/unregistering like so:
components/test/template.hbs
<div {{did-insert this.register}} {{will-destroy this.unregister}} />
components/test/component.js
@action
register(element) {
this.element = element;
}
@action
unregister() {
this.element = null;
}
Destroying the component doesn't result in an error.
This happens when mut
-ing any property with any value on destroy, by the way, not just an element or a property that has been set before.
For reference, here's the code I used to test it:
{{#if this.show}}
<Test />
{{/if}}
<Button @onClick={{toggle-action 'show' this}}>Toggle</Button>
Also, I'm not sure it makes any difference, but I'm on a canary build of Ember:
"ember-source": "https://s3.amazonaws.com/builds.emberjs.com/canary/shas/55f876ebc10bd1645e1e62fc5e0408266952259b.tgz"
"ember-cli": "github:ember-cli/ember-cli#ba9e3ea9bcad1c6e2299e40fe265cffe61d7a25b"
Any help would be appreciated!
UPDATE: It works if I use the action
helper instead of fn
. It also passes if I use ember-fn-helper-polyfill
for fn. If I use the Ember 3.11 version of fn
however, it fails with the error specified above.
With #70 being merged, and now that ember v5 is in beta channel, I think a new release is warranted here to so that consumers of this addon can test against beta without receiving a version warning.
did-insert
did-update
will-destroy
After installing ember-render-modifiers version 2.0.3 or 2.0.4 the local building process works fine, but the Gitlab pipeline fails with the error Unexpected token '.'
and nothing else in the logs. We use a docker container in the pipeline that executes ember build --environment=test
. Then it builds, cleans up and logs the error message.
Is there anything I can do to get more info about that error? Has anyone encountered that before?
Using modifiers on an element that is itself a classic Ember component (@ember/component
) doesn't seem to work.
This poses difficulties because the developer now has to 'know' what the
other component is.
This works great:
This not so much (doesn't error, doesn't execute).
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.arg2
from a function passed to thefn
helper, but the function itself was not bound to a validthis
context. Consider updating to usage of@action
.
e.g. in the example given in the code comments, the this.count
is not updated in the template...
https://github.com/emberjs/ember-render-modifiers/blob/master/addon/modifiers/did-insert.js#L29
in the callstack i see that installModifier
is called with a untrack
context
probably because of this:
#16
?
Versions of modifier manager capabilities prior to 3.22 have been deprecated. You must update to the 3.22 capabilities.
As Node 10 is coming up on EOL, I tried to update my project to Node 14 (and 12). In both cases, when I did, I got the following build error:
Build Error (broccoli-persistent-filter:Babel > [Babel: @ember/render-modifiers]) in @ember/render-modifiers/modifiers/did-insert.js
No "exports" main defined in /Users/stephen.weiss/code/olo/expo-web-client/node_modules/@ember/render-modifiers/node_modules/@babel/helper-compilation-targets/package.json
Stack Trace and Error Report: /var/folders/dz/43k2z2yn53g6g5wgzbx0gw8m0000gp/T/error.dump.f35dc8ac0b4685c4fa73ca1fd5ee7483.log
Is there anything we can do to accommodate newer Node versions? Or is there any recommended path forward?
My believe is that I am currently only using this in one place:
where handleFormInsert
is really meant to just add focus:
handleFormInsert(element) {
element.focus();
}
Hi,
I'm having issue in mulitple addons relying on ember-render-modifiers
with the ember-release
test
https://github.com/concordnow/ember-aria-tabs/runs/6172043274?check_suite_focus=true
https://github.com/concordnow/ember-sidenotes/runs/6161797973?check_suite_focus=true
It seems to be caused by https://github.com/emberjs/ember-render-modifiers/pull/58/files
@ef4 How are we supposed to fix that?
I'm getting the following error when installing this library:
error An unexpected error occurred: "https://registry.yarnpkg.com/@ember%2frender-modifiers: Not found".
When following the Glint setup as described in the README, I'm seeing the following error.
../node_modules/@ember/render-modifiers/types/-private.d.ts:1:30 - error TS2307: Cannot find module '@glint/template' or its corresponding type declarations.
import { ModifierLike } from '@glint/template';
Monorepo environment:
In the addon, locally declared as devDependency
:
"@glint/core": "^1.2.1",
"@glint/environment-ember-loose": "^1.2.1",
"@glint/template": "^1.2.1",
The dependency is declared as peer in package.json, which seems correct so I'm kind of puzzled why this error is popping up.
For now we're using glint-template-types.
I've created a reproduction of this issue which I'll attempt to describe here:
When returning a hash from the routes model hook and then passing that hash into a component as split properties <Consumer @one={{@model.one}} @two={{@model.two}} />
and then using those split properties in getters of the component to invoke did-update
an exception will be thrown when leaving the route. You can see this in the reproduction by navigating between the routes with the console open. This same thing doesn't happen if this.model
is used in place of @model
.
What I suspect is happening is that @model
gets torn down early and re-assigned to the incoming route. This causes the first property @model.first
to change which triggers did-update
to call the second getter which is now unable to access this.args.second
because it is also gone.
I've reproduced this as a synchronous action, but we're hitting this issue when did-update
calls a task which loads async state. That's why the modifier needs to trigger the action and it can't just be a getter itself.
I'm not sure if this is an issue with did-update
or a broader issue with modifiers and tracked properties using the @model
pattern, but this seemed like the right place to start.
In the process of rewriting components to Octane and using modifiers I ran into timing issues when didRender could no longer be used. The component in question renders text and based on if the text is scrollable or not adds an ‘expand text’ button, which when clicked shows the whole text without having to scroll.
See the following image for some explanation:
The problem occurs when you expand the text and then load in new text. Every time new text gets loaded the text gets collapsed by default, then it checks if the text is scrollable. But because it takes some time to render the collapsing it does not see the text as scrollable and no button is shown.
Component.js :
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking'
export default class TruncatedToggle extends Component {
@tracked
hasOverflow = false;
@tracked
opened = false;
@action
init() {
this.opened = false;
}
@action
getOverflow(element) {
this.hasOverflow = element.scrollHeight-1 > element.clientHeight;
}
@action
buttonClicked() {
this.opened = !this.opened;
}
}
Previously the getOverflow
code was in didRender in which the element scrollHeight and clientHeight gave correct values. Tried to set opened in the init() function to have some time between getting the overflow and collapsing the content, but that was in vain.
Component hbs:
<div class="truncated-toggle"
{{did-update this.init @content}}
>
<div class="truncated-toggle__content"
{{did-insert this.getOverflow}}
{{did-update this.getOverflow @content}}
>
{{{@content}}}
</div>
{{#if this.hasOverflow}}
<button {{action 'buttonClicked'}} class="btn btn--default">
{{#if this.opened}}
Collapse text
{{else}}
Expand text
{{/if}}
</button>
{{/if}}
</div>
I am able to make this work by adding a timeout:
@action
getOverflow(element) {
setTimeout(() => {
this.hasOverflow = element.scrollHeight-1 > element.clientHeight;
})
}
But this feels a bit hacky to me. Is this the way to go, or is there a solution that I do not know about?
We've seen this error popping up at various projects. The reason being we have the dependency: "@ember/render-modifier": "^1.0.0"
. With 1.0.0
it was working fine but after an upgrade to 1.0.1
we are seeing this error message:
Uncaught (in promise) TypeError: Ember._modifierManagerCapabilities is not a function
at vendor.js:89048
at RuntimeResolver._lookupModifier (vendor.js:20216)
at RuntimeResolver.lookupModifier (vendor.js:20127)
at CompileTimeLookup.lookupModifier (vendor.js:16613)
at LazyCompiler.resolveModifier (vendor.js:52478)
at vendor.js:51567
at Compilers.compile (vendor.js:51537)
at compile (vendor.js:52230)
at LazyCompiler.add (vendor.js:52424)
at CompilableProgram.compile (vendor.js:52188)
Our workaround was to specify the version of this package to v1.0.0
. That said it doesn't necessarily have to be this package cause it, but can be a very mixed constellation of packages that is causing it.
This happened when I tried to write a HOC with a parent passing a function to its child, and the function gets called when the child is inserted and going to be destroyed. I made an integration test to demonstrate the issue.
import Component from '@glimmer/component';
import { click, find, render } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { action } from '@ember/object';
import hbs from 'htmlbars-inline-precompile';
import { setupRenderingTest } from 'ember-qunit';
import { tracked } from '@glimmer/tracking';
module('Integration | Modifier | will-destroy', hooks => {
setupRenderingTest(hooks);
test('it should invoke UI re-rendering when changing tracked properties', async function(assert) {
this.owner.register(
'component:parent-component',
class extends Component {
@tracked text = '';
get message() {
return this.text;
}
@action changeText(text) {
this.text = text;
}
}
);
this.owner.register(
'template:components/parent-component',
hbs`
<div data-dummy>{{this.message}}</div>
{{yield (hash changeText=this.changeText)}}
`
);
this.set('show', true);
await render(
hbs`
<ParentComponent as |parent|>
{{#if show}}
<div
{{did-insert (fn parent.changeText "Hello")}}
{{will-destroy (fn parent.changeText "World")}}
>
</div>
{{/if}}
<button data-button {{on "click" (fn parent.changeText "World")}}>Change Text</button>
</ParentComponent>
`
);
// did-insert invokes re-rendering correctly, now the message is "Hello".
assert.strictEqual(find('[data-dummy]').innerText, 'Hello');
// trigger destroying. should change text.
this.set('show', false);
// will-destroy does not invoke re-rendering. message supposed to be "World".
assert.strictEqual(find('[data-dummy]').innerText, 'Hello');
await click('[data-button]');
// if the changeText function is called by other ways, it works seamlessly.
assert.strictEqual(find('[data-dummy]').innerText, 'World');
});
});
Also attached some dependencies info here.
"devDependencies": {
"@ember/optional-features": "^0.7.0",
"@ember/render-modifiers": "^1.0.2",
"@glimmer/component": "^0.14.0-alpha.13",
"ember-cli": "~3.13.1",
"ember-cli-babel": "^7.7.3",
"ember-source": "~3.13.2"
},
at present, these need to be added manually:
// required for @ember/element-modifiers
modifier: { definitiveCollection: 'main' },
in src/resolver.js.
Whenever there are hooks for addons to do this themselves, this addon should add the modifier collection.
The current API docs mostly show Component.extend()
style of documentation, but we should show both class extends Component {}
(with "real" decorators) and Component.extend()
(with "computed style" decorators).
given:
expected behavour: handleInsert
will be executed with ("someProp", Button, positional, named)
arguments
current behavour: rendering fails with undefined
is not a function
ref from glimmerjs/glimmer-vm#1279
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.