abdulhaq-e / ngrx-json-api

A JSON API client for ngrx
MIT License
61 stars 28 forks source link

Example application to illustrate best practices around domain model and json api #173

Open blaur opened 7 years ago

blaur commented 7 years ago

Maybe it is my lack of knowledge but then simply correct me a close the issue.

I have been working quite a bit with Angular 2 (through angular2-jsonapi) but I really want to utilise this project in a new Angular 4 application.

After reading through everything there are a few things that I am missing. How can we easily integrate the ngrx-json-api approach with an existing model (like done with decorators in angular2-jsonapi) without having to write a our own reducers on the side. The intention is of course to have one definition utilised across the entire application (and validated against only that one definition). Or maybe this is not even the intention of this project, or maybe I am getting it all wrong?

I understand we define the model definition in ResourceDefinition but can you somehow decorate existing model objects and utilise that as the resource defintion as the below example:

@JsonApiModelConfig({
    type: 'users'
})
export class User extends JsonApiModel {

    @Attribute()
    name: string;
    // ...
}

Or do we have any examples? I am really looking for best practices here.

Thanks in advance.

abdulhaq-e commented 7 years ago

That will be considered in the next version. Right now the models are weakly typed. Decorating a model just like angular2-jsonapi would be great. A new version of ngrx tools are being released and this library will follow.

remmeier commented 7 years ago

I make use of that already. An example looks like:

export module MetaAttribute{
    export interface Relationships extends MetaElement.Relationships{
        [key: string]: ResourceRelationship;
        type?: TypedOneResourceRelationship<MetaType>;
        oppositeAttribute?: TypedOneResourceRelationship<MetaAttribute>;
    }
    export interface Attributes extends MetaElement.Attributes{
        lazy?: boolean;
        association?: boolean;
        version?: boolean;
        derived?: boolean;
        lob?: boolean;
        nullable?: boolean;
        insertable?: boolean;
        updatable?: boolean;
        filterable?: boolean;
        sortable?: boolean;
        primaryKeyAttribute?: boolean;
    }
}
export interface MetaAttribute extends MetaElement, StoreResource{
    relationships?: MetaAttribute.Relationships;
    attributes?: MetaAttribute.Attributes;
}

the use of interfaces allows direct casting of the received json data. In my particular use case those interfaces are generated from backend declarations (java/katharsis),

blaur commented 7 years ago

Thanks a lot to both of you.

@remmeier First of all, that would still require you to maintain the attribute definitions in two places, right? But thanks a lot and it might be the way to go for me. Could you maybe expand a bit on how you would use it on my example? I am not really undersatnding how a MetaAttribute (maybe it is just the naming) should extend StoreResource which is essentially the object that is returned.

I understand that you can cast... So your result would be cast like this: var user = response.json... Or something similar with a map function. My problem lies in how we can combine the two so that I only have the definition once.

So if I have a User with name, email and telephone how would you then apply your example above?

Sorry to be a pain in the ass ;) Looking forward to your answer.

remmeier commented 7 years ago

what do you mean with two places? you have relationships and attributes in two classes.

The big benefit of extensing StoreResource is that you also get access to state information of ngrx-json-api about a particular resource (like whether it was updated, the unchanged state of the server, etc.). That can be quite helpful.

For user, name, email it would look like:

export module User{
      export interface Attributes extends MetaElement.Attributes{
        name?: string;
        email....
    }
}
export interface User extends MetaElement, StoreResource{
    attributes?: User.Attributes;
}

The other thin I make use of are also type-safe interfaces on top of ManyQueryResult and OneQueryResult. Then I have type-safe access to the query results.

remmeier commented 7 years ago

created a PR (https://github.com/abdulhaq-e/ngrx-json-api/pull/203) that fills some gaps in this area. http://www.crnk.io will be the first project that supports direct generation of ngrx-json-api/Typescript stubs from a existing backend model.