www
www copied to clipboard
Consuming APIs in Angular: The Model-Adapter Pattern
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/
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!
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!
Thank you, you are awesome!!!
@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)
Thanks @williamr12, I added the missing allow_headers=["*"]
argument. :-)
Woooow !!! Good Work Man
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
Would you recommend handling errors inside the adapters?
This pattern is awesome, was wanting a smart way to approach better decoupling - great share!
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?
Hi @florimondmanca. Just to say thanks :upside_down_face::beer:
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.
thanks.
this is very clean and simple. I like it.
I'm getting the same error as "freiand" . Are there any solutions?
Good But what if I want to convert my model to api json to send it to the server
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.