Ecodev / natural

Angular Material components and various utilities

Home Page:https://ecodev.github.io/natural

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

AbstractDetail should use Resolver data as is

PowerKiKi opened this issue · comments

In NaturalAbstractDetail.ngOnInit I think we should simplify like so:

- this.data = merge({model: this.service.getConsolidatedForClient()}, data[this.key]);
- this.data = merge(this.data, omit(data, [this.key]));
+ this.data = data;

If my understanding is correct we try force default values on whatever is coming from the route. But the route is already populated with default value via NaturalAbstractModelService.resolve who called getConsolidatedForClient earlier. So our current code seems to be entirely redundant as long as we properly use revolvers.

So we should double-check that resolvers are used correctly in all our projects and simplify this code.

Not exactly. While answering you, I found out there are some incoherences in resolving and defaulting data. Probably the result of many iterations.

There are two differences to take in consideration :

Default values more consistently

We should change AbstractModelService.resolve() to include getConsolidatedForClient's result when we provide an ID too. If we don't, we would loose some completion of the result. We actually do it in ngOnInit in all cases (new item or existing item).

   if (id) {
-     observable = this.getOne(id);
+     observable = merge(this.getConsolidatedForClient(), this.getOne(id)};

ngOnInit would be simplified :

- this.data = merge({model: this.service.getConsolidatedForClient()}, data[this.key]);
+ this.data = merge({model: data[this.key]);

This would have another impact : apply default values returned by the server on all resolved items. Actually, only the main one is defaulted in controller side.

Before (actually consolidated is unconsistant) :

{main: {model: consolidatedFetched } } 
{other: {model: fetchedOther } } 

After (all resolved models are consolidated) :

{main: {model: consolidatedFetched } } 
{other: {model: consolidatedFetchedOther } } 

Important : that means Resolvers must always be provided, there is no fallback. An error could be sent if nothing has been provided in data[this.key]... ?

Template access

When we resolve something, we declare it in routing this way (we can have multiple resolvers) :

{ 
resolve : { 
    action: ActionResolver,
    other: OtherResolver
    } 
}

In controller, router.data is :

{action: {model: fetchedAction, statuses : [...], priorities : [...]} }
{other: {model: fetchedOther } } 

In AbstractDetail.ngOnInit it targets data[this.key] where this.key is human setup and specific to a controller. This transform the router.data value into the controller this.data into :

 // action item is consolidated and "action" key becomes "model"
{model: consolidatedFetchedAction, statuses : [...], priorities : [...]}
{other: {model: fetchedOther } } 

At this final stage, templates access data.model.name.

If we replace ngOnInit as you suggest, we would have :

{action: {model: consolidatedFetchedAction, statuses : [...], priorities : [...]} }
{other: {model: fetchedOther } } 

And all templates should be updated to access data.action.model.name.

We can easily consolidate with first step : moving getConsolidatedForClient in resolve() and clear it from AbstractDetail.ngOnInit.

And if you are motivated to update all templates, you can process the second step : change AbstractDetail.ngOnInit as you suggest.

If we change something that impacts the template, we must adapt PanelService to expose the same object structure of resolved items to the template. Same components are used in Panel routing and Angular routing.

include getConsolidatedForClient's result when we provide an ID too

yes... but I am not sure in what case we need to add default values to something that already is persisted in DB, so assumed to be valid.

Resolvers must always be provided, there is no fallback. An error could be sent if nothing has been provided

yes

I didn't think of the impact on templates though... I also didn't realize that our current situation feels a little bit inconsistent between model and other.model:

 // action item is consolidated and "action" key becomes "model"
{model: consolidatedFetchedAction, statuses : [...], priorities : [...]}
{other: {model: fetchedOther } } 

But actually I didn't find any cases of other.model in non-panel routes templates, via the following command. So I guess we don't need to worry too much about that incoherence and focus only on default values handling, keeping the structure the same as now.

grep '--include=*.html' -hPor  'data\.\w+\.model' client/app/  | sort -u

I suggest we create a PR and review it before merging.