Configuration driven Components

45 views
Skip to first unread message

Gaurav Verma

unread,
Oct 18, 2017, 3:31:28 AM10/18/17
to Angular and AngularJS discussion
Hi.
Can anyone guide me in designing the core of a angular based platform? The idea is to develop a core and distribute it so that other applications can be built on top of that.

The core should provide various hosting components that serve as containers. The core will provide various base components to develop custom components so that they can be loaded into the core host components.

For example the core will provide a host component (like window) and within that component various other child views components) can be displayed. These child components are the components defined and declared in the modules that have dependency over core. I am new to Angular and finding hard to pen it.

Thanks in advance.

Gaurav

Sander Elias

unread,
Oct 18, 2017, 3:49:15 AM10/18/17
to Angular and AngularJS discussion
Hi Gaurav,

Not sure where you are after. Are you saying you want to develop a set of components, which are configuration/data driven? And then deliver this as a library?

Regards
Sander

Gaurav Verma

unread,
Oct 18, 2017, 3:11:57 PM10/18/17
to Angular and AngularJS discussion

Thanks for replying Sander.

I think I have narrowed down to below 3 questions:

  1. How can we load a module from a file location during AoT compilation in Angular?
  2. Can we get a list of exported Components defined in the loaded module during runtime?
  3. And how can we get metadata of a component in a module without instantiating it? I know about reflect-metadata api but I could not find a way to get metadata by component class name.

Thanks in advance.

Gaurav

Gaurav Verma

unread,
Oct 18, 2017, 3:32:00 PM10/18/17
to Angular and AngularJS discussion
Yes, I am trying to develop configuration driven components. It's somewhat like writing a NavBar component in the core library and exporting NavBarItem class. NavBar component is responsible to host multiple child components of type NavBarItem. The referring module can then implement NavBarItem to build components. 

The referring module's AppModule will use NavBar component in its template and I want all the NavBarItem components should get added to it.

Now I am stuck at the questions I mentioned in my last reply. I would appreciate your help.

Gaurav Verma

unread,
Oct 18, 2017, 4:40:44 PM10/18/17
to Angular and AngularJS discussion
I don't want to bombard with you so many replies but you know, as I am writing more to you I am getting a better picture of the problem!

I am trying to develop a core library that will provide implementation of configuration driven components than can be extended in the referring modules to create components. This library will be packaged to npm and can be installed from there.

For example - The core library, lets call it "A", provides NavBar component that can host child NavBarMenuItem components dynamically. Module "A" then exports the NavBarMenuItem component. And another module called "B" imports module "A" and creates various menu bar items by implementing NavBarMenuItem component class.

The NavBar component defined in "A" is configurable and can be configured to render NavBarMenuItem in different ways (let say horizontally or vertically). A configuration editor component NavBarEditorComponent is provided by the core which is used to make any changes to the NavBar. I can load this editor from the context menu of the NavBarComponent and make changes to it and the save it to the configuration store.

So the question is - How can I get Module "A" to know about the NavBarMenuItem components defined in module "B" so that it can create the component instances and add them to the NavBar component dynamically?

Can you think of a design and available api's in Angular which can cater these requirements?


Thanks

Sander Elias

unread,
Oct 18, 2017, 11:40:15 PM10/18/17
to Angular and AngularJS discussion
Hi Gaurav,

Currently, you need to jump to a number of hoops to get that going. There are a couple of blog's available that show you how to do this now.
However, depending on your timeframe, there might be a better solution. As officially announced om AngularMix there is now an Angular Elements Labs(experimental). I think you will find this a good fit for what it is you are trying to do.

Regards
Sander

Zlatko Đurić

unread,
Oct 19, 2017, 3:33:24 AM10/19/17
to Angular and AngularJS discussion
Hi Gaurav,

Let me also take a shot at this.

If I understand this properly, you want to have a Core module which provides NavBar as a navbar component, which can go horizontally or vertically. Additionally, the items in navbar are implemented as NavBarItem components. Perhaps you also have a NavbarService which gives programatic access to these two components. So now you publish the module and build another app to use it.

First, you want to be able to configure NavBar (parent component) as needed - that should be quite doable, a simple @Input() layout = 'horizontal'; will do these things.

Now the trickier part, in this new apop, you want the NavBar component from Core, but you want your own custom nav item instead of the core NavbarItem - right? For that, I think something like this could work:
Parent, NavBar uses 'nav-bar-item' as a selector. So in your new app, you import NavBar, but declare CustomNavItem with the same selector, which extends the original NavBarItem. Similarly in this custom module you can provide CustomService as an implementation of NavBarService, again, extending it first and overriding the methods you want altered.

And then export it all as a new module. And your app uses this other module instead of the original one.

I'm pretty sure most of this should work without fuss.

Gaurav Verma

unread,
Oct 20, 2017, 10:15:01 AM10/20/17
to Angular and AngularJS discussion
Wow that's a great direction! I will keep subscribing to their updates. But what are your thoughts on developing plugable modules in Angular? If given that problem what will be your approach?

Thanks in advance.

Gaurav

Gaurav Verma

unread,
Oct 20, 2017, 12:06:31 PM10/20/17
to Angular and AngularJS discussion
Thank you Zlatko for your response. You said  @Input() layout = 'horizontal' will allow me to configure the NavBar layout but how can I dynamically set the layout?

I am trying to drive the components by json configuration. I will give another example here - 

Let's say the core provides GridComponent, GridEditorComponent and a DesignerComponent. You can visualize designer UI as a hierarchical tree data structure with a max depth of 2 (Controls -> Grid -> GridInstances). 

The designer tree lists GridComponent at the 1st level along with other controls like "Custom Components" written in the module "B", which I was referring to in my last post.

The designer allows us to create new GridComponent / "Cusom Component" instance on the fly that gets added under their respective parent nodes of the tree. User can right click on the "Grid" node and select "New Grid" which displays GridEditorComponent view that allows user to set the component's properties like layout, alternate row color, etc along with a "unique id" before saving it. 

When you hit the save button on the editor's view, the designer component will instantiate GridComponent and and serialize it to json (so that it can be stored in a configuration store (database) for persistence) and list it under the "Grid" node of the tree with the name equals to the  "unique id" provided while creating it.

Now I should similarly be able to create another component WorkspaceComponent at runtime, which is also provided by the core and listed in the designer tree. The WorkspaceComponent has a "content" property which is of type string. This content property is set to the "unique id" of any of the grid components or custom components which we just created above or was created before or are persisted in the config store and loaded in the designer tree.

I found router-outlet in Angular that can help me achieve this but I am not really sure at this moment. I am still learning Angular, I have a C# background and I can think of a solution to this problem using Unity Container for plugable modules, MEF container for runtime composition, Reflection API for instantiating types on the fly, Serialization for serializing and deserializing instances to and from configuration store.


The questions still remain unsolved - 


- How can I get Module "A" to know about the NavBarMenuItem components defined in module "B" so that it can create the component instances and add them to the NavBar component dynamically?


 How can I instantiate a component from its class name as the components are created on fly from the configuration fetched from the store?


- When module “B” is dependent on module “A” then module A cannot be statically depend on module B due to circular dependency problem, without using reflection and runtime composition provided by MEF container how can we solve this?


Thanks for you help.

Gaurav

Zlatko Đurić

unread,
Oct 20, 2017, 6:45:03 PM10/20/17
to Angular and AngularJS discussion


On Friday, October 20, 2017 at 6:06:31 PM UTC+2, Gaurav Verma wrote:
Thank you Zlatko for your response. You said  @Input() layout = 'horizontal' will allow me to configure the NavBar layout but how can I dynamically set the layout?

This particular problem is sSimple to solve: @Input() layout: string = 'horizontal' on a component just sets the default layout. If you later have a service which loads your configuration from JSON or whatever storage, it can later set this layout to 'vertical', for example.

Now, some components may not be flexible enough to adjust on the fly - you simply do not instantiate those components into view until you have the proper 
 

I am trying to drive the components by json configuration. I will give another example here - 
[cut]

Yes, all perfectly doable within a regular Angular app. Remember, you can load the component right away or lazily, and once loaded, you can instantiate it (and provide configuration) right away or modify this configuration dynamically. It's very flexible, and you're the actual designer of your component's API, so you decide (and, well, implement) all of this.
 
 


The questions still remain unsolved - 


- How can I get Module "A" to know about the NavBarMenuItem components defined in module "B" so that it can create the component instances and add them to the NavBar component dynamically?


It's a bit vague question, so the answer is the classic of "it depends". You can provide some sort of a child module to your Module A so it knows what components it will get. You can create a module dynamically with the components you want at that instance, and then inject those. You could even (a bit less optimal) create a component itself dynamically and then pass that component to your original module so it can inject it into place or places it needs. 

 


 How can I instantiate a component from its class name as the components are created on fly from the configuration fetched from the store?


You'd generally use componentFactory to create components on the fly. Look into, e.g. ComponentFactoryResolver.
 


- When module “B” is dependent on module “A” then module A cannot be statically depend on module B due to circular dependency problem, without using reflection and runtime composition provided by MEF container how can we solve this?


You don't have to depend on B, you use an injector the component factory and create factory on the fly and add it to your component, or say, inject to a child.

Here's a plunkr demonstrating some of this: https://plnkr.co/edit/Zjne3btR82WWtokKEgHm?p=preview. It took a bit to make it all work but it basically does what you want: there's a GridCmp will take DefaultItems to construct the grid, but it will also take and insert components dynamically. And you can choose do do only one of these - so dynamic or one-off. And the components were loaded from another module. You could possibly load even that other module dynamically with NgModuleFactoryLoader. Or you could create your components right there on the fly. You could inject all those in other places, too, all over your grid-cmp template.

As for the GridComponent itself, you can also make a wrapper component there and export it in a module, and this wrapper component basically takes config instead the current one, and then creates a module dynamically, and injects the whole, ready, module. So, take a look at that and see if that answers any of your questions, and if you have more, we're here.

 Basically, it depends on what exactly you're building. A simple nav-bar would look similar to what I have made there, and something more complex like tabular page layout with different navbars, toolbars and work areas for every page will be more complex. So you need to take it from here and see what else you can make.

Gaurav Verma

unread,
Oct 23, 2017, 9:35:05 AM10/23/17
to Angular and AngularJS discussion
Thank you very much Zlatco, this is what I was looking for, an entry point. I appreciate for the time you took out to develop this plunkr. This looks great and let me try to think on top of that and will bother you if stuck again. Thanks again.
Reply all
Reply to author
Forward
0 new messages