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

Docs: Add recipe guide for using Store with custom elements #1621

Closed
brandonroberts opened this issue Mar 14, 2019 · 43 comments
Closed

Docs: Add recipe guide for using Store with custom elements #1621

brandonroberts opened this issue Mar 14, 2019 · 43 comments

Comments

@brandonroberts
Copy link
Member

@brandonroberts brandonroberts commented Mar 14, 2019

People have asked how you use a single Store across multiple custom elements.

Requirements:

  • A guide that shows how to set it up.
  • A downloadable live example under projects/ngrx.io/examples that is referenced in the guide.
@brandonroberts brandonroberts changed the title Docs: add recipe guide for using Store with custom elements Docs: Add recipe guide for using Store with custom elements Mar 14, 2019
@santoshyadavdev
Copy link
Contributor

@santoshyadavdev santoshyadavdev commented Mar 16, 2019

Hey @brandonroberts ,
I can start with this, can you tell me how should i get started,if you can guide me to any examples or demo.

@wesleygrimes
Copy link
Member

@wesleygrimes wesleygrimes commented Mar 26, 2019

@santoshyadav198613 In theory, it shouldn't be much different than implementing NgRx in a regular scenario. Custom elements can have services (injectables) injected into the constructor just like regular components.

My recommendation would be to create a GitHub repository that:

  • Implements a simple NgRx Store with a Counter (number)
  • Has a custom element that includes a button to dispatches an increment action on the store
  • Has a custom element that includes a button to dispatch an decrement action on the store
  • Has a custom element that displays the current counter value from state

Once we prove this works we can back into an article/guide that shows how to do this.

Here's the Angular docs page for custom elements: https://angular.io/guide/elements#using-custom-elements

What do you think @brandonroberts?

@santoshyadavdev
Copy link
Contributor

@santoshyadavdev santoshyadavdev commented Mar 28, 2019

Thanks @wesleygrimes ,

Will start working on the app.

Regards,
Santosh

@wesleygrimes
Copy link
Member

@wesleygrimes wesleygrimes commented Apr 1, 2019

@santoshyadav198613 any luck on the app? I was thinking about taking a crack at this, but don't want to steal your thunder.

@santoshyadavdev
Copy link
Contributor

@santoshyadavdev santoshyadavdev commented Apr 1, 2019

Hey @wesleygrimes,
I am travelling right now, will start working from tomorrow, you will have something to review by this weekend.

Regards,
Santosh

@wesleygrimes
Copy link
Member

@wesleygrimes wesleygrimes commented Apr 1, 2019

@santoshyadav198613 Sounds good my friend!

@wesleygrimes
Copy link
Member

@wesleygrimes wesleygrimes commented Apr 2, 2019

@santoshyadav198613 this is looking good! Can you take it a step further and make each piece a separate custom element? Right now it's all together in one counter element, but I think the end goal is to show multiple counter elements communicating with each other through the Store.

@santoshyadavdev
Copy link
Contributor

@santoshyadavdev santoshyadavdev commented Apr 2, 2019

@wesleygrimes

@santoshyadav198613 this is looking good! Can you take it a step further and make each piece a separate custom element? Right now it's all together in one counter element, but I think the end goal is to show multiple counter elements communicating with each other through the Store.

thanks sure will start working on it.

@santoshyadavdev
Copy link
Contributor

@santoshyadavdev santoshyadavdev commented Apr 3, 2019

Hi @wesleygrimes ,
Please verify now, we have 4 elements.

@wesleygrimes
Copy link
Member

@wesleygrimes wesleygrimes commented Apr 3, 2019

Hi @wesleygrimes ,
Please verify now, we have 4 elements.

@santoshyadav198613 This is looking good!

@timdeschryver @brandonroberts What do you think? Should the example go any further like showing the elements being used in a non-angular, vanilla js scenario? Or is this good enough?

@santoshyadavdev
Copy link
Contributor

@santoshyadavdev santoshyadavdev commented Apr 6, 2019

Hi @timdeschryver @brandonroberts ,

Any update to move forward with this task.

@brandonroberts
Copy link
Member Author

@brandonroberts brandonroberts commented Apr 6, 2019

I think it's a good start. Probably would be better to build the components in a separate lib and use them in the example.

@santoshyadavdev
Copy link
Contributor

@santoshyadavdev santoshyadavdev commented Apr 6, 2019

Sounds good, will make the changes.

@santoshyadavdev
Copy link
Contributor

@santoshyadavdev santoshyadavdev commented Apr 8, 2019

Hi @brandonroberts ,

Added a library project, the only problem is it is not working on stackblitz.
But verified locally works fine. Let me know if any changes needed.

@wesleygrimes
Copy link
Member

@wesleygrimes wesleygrimes commented Apr 8, 2019

@brandonroberts
Copy link
Member Author

@brandonroberts brandonroberts commented Apr 8, 2019

@santoshyadav198613 looks good to me!

@santoshyadavdev
Copy link
Contributor

@santoshyadavdev santoshyadavdev commented Apr 8, 2019

@santoshyadav198613 looks good to me!

thanks @brandonroberts So where we want the documentation to be added.

@timdeschryver
Copy link
Member

@timdeschryver timdeschryver commented Apr 8, 2019

I wasn't up to date with Angular elements, but this is neat!
Good job @santoshyadav198613 😄
You should consider writing a post about this, I'm sure Angular in Depth would publish it if you would like to.

@santoshyadavdev
Copy link
Contributor

@santoshyadavdev santoshyadavdev commented Apr 8, 2019

Thanks @timdeschryver ,

Sure will start writing in weekend, would be happy if you can review it before i publish.

@brandonroberts
Copy link
Member Author

@brandonroberts brandonroberts commented Apr 8, 2019

Definitely agree. A post on this would be good

@wesleygrimes
Copy link
Member

@wesleygrimes wesleygrimes commented Apr 8, 2019

@santoshyadav198613 Feel free to send any draft of the post my way (and I'm sure the other guys too) and we will be happy to review, edit, etc... before you publish.

@wesleygrimes
Copy link
Member

@wesleygrimes wesleygrimes commented Apr 10, 2019

@santoshyadav198613 we will review. Certainly has potential to be a great read!

@wesleygrimes
Copy link
Member

@wesleygrimes wesleygrimes commented Apr 10, 2019

We should also think about getting this or similar content into a recipes page in the docs for NgRx now that you have proved it works.

@siddharthpal
Copy link

@siddharthpal siddharthpal commented Apr 11, 2019

@brandonroberts @wesleygrimes Can we have one example of custom element's exposed method where we call a ngrx action. I was trying to work with custom elements + NgRX and tried to integrate the custom element in an angularjs app. Amazed to see everything working seamlessly!!! But I am stuck at one place. Whenever from my angularjs app I am calling the custom element exposed method change detection is not happening.

Calling code in angular js
const customElement= angular.element('hello-ce')[0]; customElement.refreshSettingProgressValue(settingsPage);

Exposed method in Angular 7 + @ngrx/store(7.3.0) + Custom Elements:

  ngOnInit(): void {
    this.isLoading$ = this.store.pipe(select(landingPageQuery.getLoading));
    this.categories$ = this.store.pipe(
      select(landingPageQuery.getAllLandingPage)
    );
  }
  @Input()
  public refreshSettingProgressValue = function (this: CompType, settingCategoryCode: string) {
    this.categories$.pipe(
      mergeMap(categories => categories),
      map(category => category.settings),
      mergeMap(settings => settings),
      filter(setting => setting.settingCodeType.code === settingCategoryCode),
      take(1)
    ).subscribe({
      next: (setting) => {
        this.store.dispatch(new ResetSettingsProgressValue(setting));
        this.store.dispatch(new LoadSettingsProgressValue(setting));
      }
    })
  }.bind(this);

I tried calling the _refreshSettingProgressValue _ inside Angular7 app on click of a dummy button and everything works but when I call it outside Angular context I am not able to see the changes in UI.
P.S LoadSettingsProgressValue has an effect where we call some api. I see the call is also happening and reducer is also updating the state but change detection doesn't seem to kick in.

I have already tried ngzone-element-strartergy but it didnt resolve my issue

  ngDoBootstrap(): void {
    const elements: any[] = [
      [HelloWorldComponent, 'hello-ce'],
    ];
    for (const [component, name] of elements) {
      const strategyFactory = new ElementZoneStrategyFactory(component, this.injector);
      const el = createCustomElement(component, { injector: this.injector, strategyFactory  });
      customElements.define(name, el);
    }
  }

I believe we can call changeDetection explicitly but with ngrx how and where can we do that?

Thanks
Sid

@timdeschryver
Copy link
Member

@timdeschryver timdeschryver commented Apr 11, 2019

Happy to hear this also works for AngularJS 😄
I agree that you'll have to trigger Angular's CD here.

I think currently the only options would be to listen to actions inside the component itself or a better way would to trigger the CD when the select emits a new value.

this.categories$ = this.store.pipe(
      select(landingPageQuery.getAllLandingPage)
      tap(_ => this.changeDetectionRef.detectChanges())
);
@santoshyadavdev
Copy link
Contributor

@santoshyadavdev santoshyadavdev commented Apr 12, 2019

Hi Guys,
Let me know where we can add this in guide section, also reviews for blog please.

@siddharthpal
Copy link

@siddharthpal siddharthpal commented Apr 12, 2019

@timdeschryver
Finally could get the change detected by running inside ngZone like below:

  this.ngZone.run(() => {
        this.store.dispatch(new ResetSettingsProgressValue(setting));
        this.store.dispatch(new LoadSettingsProgressValue(setting));
  });

Tried firing change detection on every emit value after

    this.categories$ = this.store.pipe(
      select(landingPageQuery.getAllLandingPage),
      tap(_ => this.changeDetectionRef.detectChanges())
    );

but it doesn't work!!!. I am not sure why. Can anyone please have an explanation.
Thanks

@santoshyadavdev
Copy link
Contributor

@santoshyadavdev santoshyadavdev commented Apr 15, 2019

HI @wesleygrimes @timdeschryver ,
Should i publish it.

@santoshyadavdev
Copy link
Contributor

@santoshyadavdev santoshyadavdev commented Apr 15, 2019

Thanks for review @brandonroberts , i have made the changes.

@brandonroberts
Copy link
Member Author

@brandonroberts brandonroberts commented Apr 15, 2019

I didn't make it all the way through. I will leave more feedback later today

@wesleygrimes
Copy link
Member

@wesleygrimes wesleygrimes commented Apr 30, 2019

@santoshyadav198613 Now that you have the blog posted, would you be willing to work on submitting a PR that morphs the blog post into a guide for the docs? I suspect there will be a lot of back and forth, but it would be helpful to get this started. If you need help on submitting PR's for docs, let us know.

@santoshyadavdev
Copy link
Contributor

@santoshyadavdev santoshyadavdev commented May 1, 2019

Sure @wesleygrimes PR coming soon.

@santoshyadavdev
Copy link
Contributor

@santoshyadavdev santoshyadavdev commented May 1, 2019

One thing guys, if we add this example, we have already seen Angular Libraries are not supported on StackBlitz. We can give only download option.

@santoshyadavdev
Copy link
Contributor

@santoshyadavdev santoshyadavdev commented May 4, 2019

Hi @brandonroberts , @wesleygrimes where to add the guide, should I add it in Recipes section under Getting Started of Store.

santoshyadavdev added a commit to santoshyadavdev/platform that referenced this issue May 4, 2019
@santoshyadavdev santoshyadavdev mentioned this issue May 4, 2019
2 of 3 tasks complete
@wesleygrimes
Copy link
Member

@wesleygrimes wesleygrimes commented May 4, 2019

santoshyadavdev added a commit to santoshyadavdev/platform that referenced this issue May 5, 2019
santoshyadavdev added a commit to santoshyadavdev/platform that referenced this issue May 6, 2019
santoshyadavdev added a commit to santoshyadavdev/platform that referenced this issue May 8, 2019
santoshyadavdev added a commit to santoshyadavdev/platform that referenced this issue May 11, 2019
@timdeschryver timdeschryver moved this from To do to In progress in NgRx Docs May 23, 2019
@METACEO
Copy link

@METACEO METACEO commented Jun 1, 2019

I read the title thinking of a different scenario, maybe it's easier to implement?
For example, if I had counter-ng-element that keeps its own state, say { counter: number; } - how can element instances get a new store instance? I would like to develop a component knowing that I don't have to worry about multiple instances interfering or sharing each other's states.

Edit: is this worthy of a new issue or a separate story?

santoshyadavdev added a commit to santoshyadavdev/platform that referenced this issue Jun 23, 2019
@houssein-khafaja
Copy link

@houssein-khafaja houssein-khafaja commented May 4, 2020

Nice article! @santoshyadav198613
Any chance you could do the same for Angular 9? Or do you think it would work out the same way as it did in Angular 7?

@brandonroberts
Copy link
Member Author

@brandonroberts brandonroberts commented Jul 10, 2020

Closing this for now

NgRx Docs automation moved this from In progress to Done Jul 10, 2020
@Ashwin2488
Copy link

@Ashwin2488 Ashwin2488 commented Jul 17, 2020

I read the title thinking of a different scenario, maybe it's easier to implement?
For example, if I had counter-ng-element that keeps its own state, say { counter: number; } - how can element instances get a new store instance? I would like to develop a component knowing that I don't have to worry about multiple instances interfering or sharing each other's states.

Edit: is this worthy of a new issue or a separate story?

@METACEO Any update on this? Need my element instances have separate store instances so that they don't interfere.

@METACEO
Copy link

@METACEO METACEO commented Jul 18, 2020

@Ashwin2488 nah, I haven't experimented with anything like this in awhile. If I had to jump back into this today, I'd probably start with this @ngrx/component-store - how does this look to you?

@METACEO
Copy link

@METACEO METACEO commented Aug 19, 2020

FYI @Ashwin2488, sure enough, ngrx/component-store seems to be a good lead!

Local state management with @ngrx/component-store by Alex Okrushko || Angular Conference
https://www.youtube.com/watch?v=zMtubR7etsE

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
NgRx Docs
  
Done
Linked pull requests

Successfully merging a pull request may close this issue.

8 participants
You can’t perform that action at this time.