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

fix(lib, media-query): support angular/universal #353

Merged
merged 1 commit into from
Aug 4, 2017

Conversation

ThomasBurleson
Copy link
Contributor

@ThomasBurleson ThomasBurleson commented Jul 29, 2017

Use getDom() for platform-server/universal fixes.
Now gets document object from platform-browser by DI instead of global.

  • Add universal application to packages

Fixes #187, #354. Closes #346.

Thx to @ardatan for PR #346.

constructor(ref: ElementRef) {
const getMouseEventPosition = (event: MouseEvent) => ({x: event.movementX, y: event.movementY});

const mouseup$ = Observable.fromEvent(document, 'mouseup');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you have to inject 'DOCUMENT' from 'platform-browser'.

Copy link
Contributor Author

@ThomasBurleson ThomasBurleson Jul 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ardatan - true. I think even better is to use ref.nativeElement.ownerDocument. Your thoughts ?

Copy link

@ardatan ardatan Jul 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ThomasBurleson I am not sure if platform-server has ownerDocument property implementation.

@ThomasBurleson
Copy link
Contributor Author

@ardatan - BTW, even with injection or ownerDocument I am still getting gulp ci:prerender errors:

11:14:25] 'prerender' errored after 611 ms
[11:14:25] Error: ERROR TypeError: Invalid event target
    at Function.FromEventObservable.setupSubscription (/Users/thomasburleson/Documents/projects/Google/projects/angular-layouts/node_modules/rxjs/observable/FromEventObservable.js:113:19)
    at FromEventObservable._subscribe (/Users/thomasburleson/Documents/projects/Google/projects/angular-layouts/node_modules/rxjs/observable/FromEventObservable.js:135:29)
    at FromEventObservable.Observable._trySubscribe (/Users/thomasburleson/Documents/projects/Google/projects/angular-layouts/node_modules/rxjs/Observable.js:171:25)
    at FromEventObservable.Observable.subscribe (/Users/thomasburleson/Documents/projects/Google/projects/angular-layouts/node_modules/rxjs/Observable.js:159:65)
    at MapOperator.call (/Users/thomasburleson/Documents/projects/Google/projects/angular-layouts/node_modules/rxjs/operator/map.js:54:23)
    at Observable.subscribe (/Users/thomasburleson/Documents/projects/Google/projects/angular-layouts/node_modules/rxjs/Observable.js:156:22)
    at SwitchMapOperator.call (/Users/thomasburleson/Documents/projects/Google/projects/angular-layouts/node_modules/rxjs/operator/switchMap.js:67:23)
    at Observable.subscribe (/Users/thomasburleson/Documents/projects/Google/projects/angular-layouts/node_modules/rxjs/Observable.js:156:22)
    at SplitDirective.ngAfterContentInit (/Users/thomasburleson/Documents/projects/Google/projects/angular-layouts/dist/packages/universal-app/app/splitter/split.directive.js:18:41)
    at callProviderLifecycles (/Users/thomasburleson/Documents/projects/Google/projects/angular-layouts/node_modules/@angular/core/bundles/core.umd.js:11206:18)

Any ideas ?

@ardatan
Copy link

ardatan commented Jul 30, 2017

in 'split-handle-directive.ts', I think it had better to take events into Observable by using HostListener. I changed like that, and ran ci:prerender. It was successful. You can try.
BTW, ngAfterViewInit looks better than ctor.

import {Directive, ElementRef, Output, Inject, EventEmitter, HostListener} from '@angular/core';
import {DOCUMENT} from '@angular/platform-browser';
import {Observable} from 'rxjs/Observable';

import 'rxjs/add/observable/fromEvent';
import 'rxjs/add/operator/takeUntil';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/map';

@Directive({
  selector: '[ngxSplitHandle]',
  host: {
    class: 'ngx-split-handle',
    title: 'Drag to resize'
  }
})
export class SplitHandleDirective {

  @Output() drag: Observable<{ x: number, y: number }>;
  mousedown$ = new EventEmitter();

  constructor(private ref: ElementRef, @Inject(DOCUMENT) private document: any) { }
  ngAfterViewInit() {
    const getMouseEventPosition = (event: MouseEvent) => ({ x: event.movementX, y: event.movementY });

    const mouseup$ = Observable.fromEvent(this.document, 'mouseup');
    const mousemove$ = Observable.fromEvent(this.document, 'mousemove')
      .map(getMouseEventPosition);
    this.drag = this.mousedown$.switchMap(_ => mousemove$.takeUntil(mouseup$));

  }
  @HostListener('mousedown', ['$event']) onMouseDown(event) {
    this.mousedown$.next(event);
  }

}

@ThomasBurleson ThomasBurleson force-pushed the thomas/issue-187 branch 2 times, most recently from d3acdbe to 1f62f0c Compare July 30, 2017 18:06
@ThomasBurleson
Copy link
Contributor Author

@ardatan - fixed it. Need to use isBrowser() utility method.

@ardatan
Copy link

ardatan commented Jul 30, 2017

@ThomasBurleson it is ready to merge?

@ThomasBurleson
Copy link
Contributor Author

@ardatan - we have a rigorous merge process that includes tests with many applications internal to Google. This will be marked as presubmit. The merge process may take 2-3 work days.

@ardatan
Copy link

ardatan commented Jul 30, 2017 via email

@ardatan
Copy link

ardatan commented Jul 31, 2017

@ThomasBurleson I have an idea about pre-rendered flex-layout pages. Now when we are using flex-layout with universal, it only applies default styles than changes by current screen.
But here is the thing, we can prevent that bad-looking issue by changing the approach.
1)We can predict screen size by using user-agent from request(which is available in platform-server/not-implemented but could be)
2)We can apply all styles by using media queries.

What do you think?

@ThomasBurleson ThomasBurleson changed the title fix(lib, media-query): use getDom() for platform-server/universal fixes fix(lib, media-query): support angular/universal Aug 2, 2017
let findDirection = (styles) => directionKeys.reduce((direction, key) => {
return direction || styles[key];
}, null);
let immediateValue = getDom().getStyle(target, 'flex-direction');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this logic appears twice, move to helper function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@@ -19,13 +20,14 @@ export class SplitHandleDirective {

constructor(ref: ElementRef) {
const getMouseEventPosition = (event: MouseEvent) => ({x: event.movementX, y: event.movementY});
const document = ref.nativeElement.ownerDocument;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see elsewhere you are doing @Inject(DOCUMENT) why not same here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will sync the solutions to be the same. Thx.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

let canListen = !!(<any>window).matchMedia('all').addListener;
return canListen ? (<any>window).matchMedia(query) : <MediaQueryList>{
protected _buildMQL(query: string): MediaQueryList {
let canListen = (typeof matchMedia != 'undefined');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can just do canListen = !!matchMedia or not even and just do:

if (matchMedia) {
  ...
}
return matchMedia ? ...;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will use the angular Universal isBrowser() solution.

outline: none;
-webkit-user-select: none;
user-select: none;
z-index: 9999;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does the z-index need to be so high?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just chose an arbitrary large 100.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

top: 50%;
left: -2px;
transform: translateX(-50%) rotate(270deg);
cursor: col-resize;;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

double ;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@ThomasBurleson ThomasBurleson force-pushed the thomas/issue-187 branch 2 times, most recently from 534f14c to 56a53f6 Compare August 2, 2017 18:11
@ThomasBurleson
Copy link
Contributor Author

@mmalerba - all comments fixed. Thank you sir.

@mmalerba mmalerba added the pr: lgtm This PR has been approved by the reviewer label Aug 2, 2017
Use getDom() for platform-server/universal fixes
Now gets document object from platform-browser by DI instead of global.

> Thx to @ardatan for PR #346.

Fixes #187, #354. Closes #346.
@cyrilletuzi
Copy link
Contributor

With last head build, Universal still does not work with Flex Layout, got these errors :

ReferenceError: document is not defined
    at prepareQueryCSS (/node_modules/@angular/flex-layout/bundles/flex-layout.umd.js:834:34)
    at MatchMedia.exports.MatchMedia.MatchMedia._buildMQL (/node_modules/@angular/flex-layout/bundles/flex-layout.umd.js:802:9)
    at MatchMedia.exports.MatchMedia.MatchMedia.registerQuery (/node_modules/@angular/flex-layout/bundles/flex-layout.umd.js:788:28)
    at /node_modules/@angular/flex-layout/bundles/flex-layout.umd.js:1063:31
    at Array.forEach (native)
    at MediaMonitor.exports.MediaMonitor.MediaMonitor._registerBreakpoints (/node_modules/@angular/flex-layout/bundles/flex-layout.umd.js:1062:33)
    at new MediaMonitor (/node_modules/@angular/flex-layout/bundles/flex-layout.umd.js:995:14)
    at MEDIA_MONITOR_PROVIDER_FACTORY (/node_modules/@angular/flex-layout/bundles/flex-layout.umd.js:1525:29)
    at _callFactory (/node_modules/@angular/core/bundles/core.umd.js:9585:26)
    at _createProviderInstance$1 (/node_modules/@angular/core/bundles/core.umd.js:9521:26)
ERROR { Error: Uncaught (in promise): ReferenceError: window is not defined
ReferenceError: window is not defined
    at MatchMedia.exports.MatchMedia.MatchMedia._buildMQL (/node_modules/@angular/flex-layout/bundles/flex-layout.umd.js:803:27)
    at MatchMedia.exports.MatchMedia.MatchMedia.registerQuery (/node_modules/@angular/flex-layout/bundles/flex-layout.umd.js:788:28)
    at /node_modules/@angular/flex-layout/bundles/flex-layout.umd.js:1063:31
    at Array.forEach (native)
    at MediaMonitor.exports.MediaMonitor.MediaMonitor._registerBreakpoints (/node_modules/@angular/flex-layout/bundles/flex-layout.umd.js:1062:33)
    at new MediaMonitor (/node_modules/@angular/flex-layout/bundles/flex-layout.umd.js:995:14)
    at MEDIA_MONITOR_PROVIDER_FACTORY (/node_modules/@angular/flex-layout/bundles/flex-layout.umd.js:1525:29)
    at _callFactory (/node_modules/@angular/core/bundles/core.umd.js:9585:26)
    at _createProviderInstance$1 (/node_modules/@angular/core/bundles/core.umd.js:9521:26)
    at resolveNgModuleDep (/node_modules/@angular/core/bundles/core.umd.js:9503:17)
  
rejection:
   { ReferenceError: window is not defined
       at MatchMedia.exports.MatchMedia.MatchMedia._buildMQL (/node_modules/@angular/flex-layout/bundles/flex-layout.umd.js:803:27)
       at MatchMedia.exports.MatchMedia.MatchMedia.registerQuery (/node_modules/@angular/flex-layout/bundles/flex-layout.umd.js:788:28)
       at /node_modules/@angular/flex-layout/bundles/flex-layout.umd.js:1063:31
       at Array.forEach (native)
       at MediaMonitor.exports.MediaMonitor.MediaMonitor._registerBreakpoints (/node_modules/@angular/flex-layout/bundles/flex-layout.umd.js:1062:33)
       at new MediaMonitor (/node_modules/@angular/flex-layout/bundles/flex-layout.umd.js:995:14)
       at MEDIA_MONITOR_PROVIDER_FACTORY (/node_modules/@angular/flex-layout/bundles/flex-layout.umd.js:1525:29)

Does not crash the server, but stop rendering all the rest of the page.

@ThomasBurleson
Copy link
Contributor Author

ThomasBurleson commented Aug 9, 2017

@cyrilletuzi - we need your help to reproduce this issue. Do you have a small demo that we can test locally to produce the same error ? Also please create a new issue for this... or add extra information to issue #354.

@cyrilletuzi
Copy link
Contributor

Sorry, it was just a package synchronisation issue (I updated my app flex layout package but not the server one...), all is OK now and I can close the reflect issue.

Is it possible to release a beta.9 for this ? I suppose if it's not still here yet it's because there are other things coming, but as it's a beta release it is not critical to miss some other points and would be better than rely on nightly builds.

@ThomasBurleson
Copy link
Contributor Author

@cyrilletuzi - thx for the follow-up and confirmation/closure of your issue. We hope to release Beta.9 this week.

@wis
Copy link

wis commented Aug 11, 2017

great OSS work guys.
happy to hear that material and flex-layout work OOB with Universal now after beta 9 releasi this week 🎉.
@ThomasBurleson what about what @ardatan mentioned above? ;
theres libs for predicting specific device & if Desktop/Mobile from user agent of Express request, we can map it to exact width value for mobile devices and close enough one (1080p?) for desktop, for much better html render.
is there a way to make universal render to specified width?

@cyrilletuzi
Copy link
Contributor

@wesamco It's discussed in #373

@angular angular locked and limited conversation to collaborators Aug 11, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
cla: yes pr: lgtm This PR has been approved by the reviewer pr: needs presubmit ssr
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Using flex-layout with Angular Universal
7 participants