Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

window and Event are undefined in Ember Fastboot #4

Closed
realityendshere opened this issue Aug 5, 2016 · 9 comments
Closed

window and Event are undefined in Ember Fastboot #4

realityendshere opened this issue Aug 5, 2016 · 9 comments

Comments

@realityendshere
Copy link

Hi!

I find this library to be super helpful. Thanks for sharing it with the world!

I was experimenting with Ember Fastboot. Since Fastboot renders on the server, some browser functionality is missing. For example, window, document, and Event are not defined.

This leads to trouble when trying to setup the custom eq-update event in addon/trigger.js. Fastboot tries to define the new event and throws an error that prevents successful rendering.

To address this, I added some quick checks to make sure Event and window are defined.

export const event = (typeof Event !== 'undefined') ? new Event('eq-update') : null;

export default function trigger() {
  if (window && event) {
    return window.dispatchEvent(event);
  }
}

I'll open a PR in a moment. I hope that helps.

Thanks again.

@lolmaus
Copy link
Owner

lolmaus commented Aug 6, 2016

Hey Dana! Thank you for interest in my addon and many thanks for the PR!

I've taken a more radical approach here and removed the dependency on Event alltogether. Instead, I'm now using an eq service infused with Ember.Evented. Event name is shouldUpdate and there's a convenience method .update() which triggers that event on the service, and all element query components react.

Please try the the version of the addon from this PR: #6, and tell me if it works for you. I think ember i lolmaus/ember-element-query#use-ember-evented should work.

PS Please read about other changes in that branch's changelog.

@realityendshere
Copy link
Author

Thanks!

I finally got to trying the ember evented branch with my fastboot experiment and it seems to work so far. I'll re-open this issue if needed.

Thanks again.

@lolmaus
Copy link
Owner

lolmaus commented Aug 9, 2016

Please keep in mind the release date is undefined. I work on it occasionally, mostly when myself or someone like you stumbles on a problem and demands a fix. There's a roadmap in the changelog with no ETA.

Ideas and opinions are welcome. For example, have you ever faced a need to subscribe to an EQ update of a given element? I. e. not trigger a refresh, but to react to a refresh.

PS Don't depend on a branch name, depend on a commit hash. Branches get deleted and cause build failures.

@realityendshere
Copy link
Author

Oh. I totally understand and appreciate that you've shared your work with the community.

I use this mixin on a component that displays a media thumbnail or a video player. Aside from styles to hide UI when it doesn't fit anymore, I use some of the eq properties to compute which size of thumbnail to display or determine if there is enough room for the video player. The element size may also be changed by a range input that alters element size. Changes to this sizing preference trigger "events" (now sent through the service) that the eq mixin detects.

I hope that answers your question about how I am using the mixin.

@lolmaus
Copy link
Owner

lolmaus commented Aug 9, 2016

Woah, I'm so proud you're using my addon for such an advanced use case!

My use cases are merely to simplify my Sass structure by avoiding complex media queries. :trollface:

Ok, lets think of a hypothetical scenario. Can you think of a use case that would require the e-q element to trigger a method. Say, it decided to resize, and now you need to notify a third party video player to rearrange its UI. Does it sound legit?

@realityendshere
Copy link
Author

Depending on what UI was being changed; yes, that could be a use case.

Hopefully, SASS could address the majority of UI re-arranging use cases. I definitely use SASS to manipulate the layout of elements as they change size.

But there may be cases where, for example, an element size changes and the video needs to pause or play at a certain threshold. This is behavior that cannot be accomplished with styles alone. Since your mixin already watches for resize events, it's useful to observe for triggering certain behaviors.

@lolmaus
Copy link
Owner

lolmaus commented Aug 9, 2016

It could also be useful when a third-party library uses inline styles applied from JS in order to position controls absolutely.

In those cases we'll need an afterUpdate event. But it makes no sense to use the service as a target, because every e-q component would trigger it, and the event will be triggered multiple times for a single shouldUpdate.

This means that the component itself should be a target for the afterUpdate event. Does it make sense?

What is the most convenient way to expose that? It would be trivial to hook to that event if you use the mixin form of ember-element-query. But if you use the {{#e-q}} component, you want it to yield the event target... E. g.:

{{! parent-component.hbs}}

{{#e-q as |eqYieldable|}}
  {{child-component
    eqEventTarget = eqYieldable.eventTarget
  }}
{{/e-q}}
// child-component.js

Ember.on('didInsertElement', function () {
  this.get('eqEventTarget').on('afterUpdate', () => ThirdPartyLib.rearrange());
})

Does that make sense? Any alternative ideas?

@realityendshere
Copy link
Author

Ember seems pretty opinionated about the "data down, actions up" paradigm. If I am understanding your example code correctly, firing events from a parent component downwards seems like it fights with the current philosophies of Ember and may lead to problems in future versions of the framework.

I'd try to manipulate child components with data or shared services. This seems to work in a significant majority of use cases. If dynamic styles need to be manipulated on resize, I'd extend an existing component and inject overrides as needed to shape the behavior I want.

I hope that helps.

@lolmaus
Copy link
Owner

lolmaus commented Aug 10, 2016

I agree that it feels weird, and I don't particularly like it myself. It was just a quick thought experiment, a raw idea.

But technically I'm not violating DDAU. I'm passing down an object, something similar to a model. DDAU does not forbid mixing Evented into data.

manipulate child components with data

Like passing a boolean value instead of an event target and toggling the boolean every time an event happens? It's kinda ugly to me, and I don't see what specifically is the Evented approach is inferior in, compared to that.

manipulate child components with shared services

The problem here is that event listeners will have to distinguish between afterUpdate fired by different components. We'll have to use channels (.trigger('afterUpdate', 'foo')) or unique event names (.trigger('afterUpdate-foo')). Either way is cumbersome. Components don't initially have names, a user will have to pass a name to every component. For components created in a loop he'll have to do name = (concat "bla-bla-" i)...

Then it opens a technical possibility to subscribe to the event from the outside and keep subscribed even after the related component is destroyed. If a new subscription will happen every time a user visits the route, we have a memory leak.

If dynamic styles need to be manipulated on resize, I'd extend an existing component and inject overrides as needed to shape the behavior I want.

Well, what if a child component has to depend on a parent component's size? E. g. when parent resizes, the child should trigger a resize on a third-party library.

I have to decide whether this use case is rare enough to ignore it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants