www icon indicating copy to clipboard operation
www copied to clipboard

Consuming APIs in Angular: The Model-Adapter Pattern

Open utterances-bot opened this issue 4 years ago • 17 comments

Consuming APIs in Angular: The Model-Adapter Pattern

A TypeScript-friendly pattern to improve how you integrate Angular apps and REST APIs.

https://florimond.dev/blog/articles/2018/09/consuming-apis-in-angular-the-model-adapter-pattern/

utterances-bot avatar Jul 29 '20 17:07 utterances-bot

Hello Florimond.

Your tutorial looks like its exactly what I am looking for!

However, I am not getting app.py to run. I get a TypeError: init() on line 3, "unexpected argument 'enable_cors'"

Do you know what cold be causing that?

Thank you!

williamr12 avatar Aug 24 '20 21:08 williamr12

Hi @williamr12, I suppose you meant to refer to the Python server code snippet in the follow-up article, Displaying Data in Components? :-) It used Bocadillo which is an abandoned project of mine. I just updated the post to use Starlette instead, and the server should run fine now. Thanks!

florimondmanca avatar Aug 25 '20 10:08 florimondmanca

Thank you, you are awesome!!!

williamr12 avatar Aug 25 '20 13:08 williamr12

@florimondmanca, I still couldn't get app.py to work. I changed it to the following format (as in this example: https://github.com/encode/starlette/issues/510). And now it works!

# Install: `pip install starlette uvicorn`
import uvicorn
from starlette.applications import Starlette
from starlette.middleware import Middleware
from starlette.middleware.cors import CORSMiddleware
from starlette.responses import JSONResponse
from starlette.routing import Route

COURSES = [
    {
        "id": 1,
        "code": "adv-maths",
        "name": "Advanced Mathematics",
        "created": "2018-08-14T12:09:45",
    },
    {
        "id": 2,
        "code": "cs1",
        "name": "Computer Science I",
        "created": "2018-06-12T18:34:16",
    },
]

app = Starlette()
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_headers=["*"],
    allow_methods=["*"],
    )

@app.route("/courses")
async def courses_list(request):
    return JSONResponse(COURSES)


if __name__ == "__main__":
    uvicorn.run(app)

williamr12 avatar Aug 25 '20 14:08 williamr12

Thanks @williamr12, I added the missing allow_headers=["*"] argument. :-)

florimondmanca avatar Aug 25 '20 20:08 florimondmanca

Woooow !!! Good Work Man

kohchangjue avatar Sep 13 '20 09:09 kohchangjue

absolutely, this is a very helpful article, I liked reading this also https://stackoverflow.com/questions/63964124/angular-convert-api-data-into-new-data-type-in-reusable-clean-method?noredirect=1&lq=1

dancoltonart avatar Sep 20 '20 09:09 dancoltonart

Would you recommend handling errors inside the adapters?

wederer avatar Sep 21 '20 12:09 wederer

This pattern is awesome, was wanting a smart way to approach better decoupling - great share!

gscottqueen avatar Dec 15 '20 18:12 gscottqueen

For me on Angular 11, the line map((data: any[]) => data.map((item) => this.adapter.adapt(item))) in CourseService doesn't compile. I get the error: Argument of type 'OperatorFunction<any[], Course[]>' is not assignable to parameter of type 'OperatorFunction<Object, Course[]>'. The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead? Type 'Object' is missing the following properties from type 'any[]': length, pop, push, concat, and 26 more.ts(2345) Any ideas what's wrong?

freiand avatar Jan 03 '21 12:01 freiand

Hi @florimondmanca. Just to say thanks :upside_down_face::beer:

luismisanchez avatar Jan 31 '21 09:01 luismisanchez

Hi, thank you, this is awesome ! I implemented it in my app and it works like a charm.

Silly question maybe, but how about using this for POST requests ?

For instance :

onSubmit(): void {
    // Create object from form
    const newAuthor = this.adapter.adapt(this.authorForm.value);

    // API POST request
    this.authorService.createAuthor(newAuthor);

    // ...
}

Do you think it's a good practice ? Or worst idea ever ?

Thanks again for this article.

shyimg avatar Feb 04 '21 10:02 shyimg

thanks.

Wayxiu avatar Apr 03 '21 04:04 Wayxiu

this is very clean and simple. I like it.

nullbytesoftware avatar May 03 '21 14:05 nullbytesoftware

I'm getting the same error as "freiand" . Are there any solutions?

awwwer avatar May 04 '21 16:05 awwwer

Good But what if I want to convert my model to api json to send it to the server

aymangithub avatar Sep 13 '21 18:09 aymangithub

Calling this an adapter is a misnomer. What you have implemented is just a mapper class between your dto and FE domain model.

The key attribute of an adapter is that you are encapsulating a class that doesn’t implement an interface you have a need to use directly and using that encapsulated class to implement the interface you need.

WardenUnleashed avatar Oct 13 '22 17:10 WardenUnleashed