troyanskiy / ngx-resource-core

RESTful Core Library
40 stars 10 forks source link

Crud update not available, no body in create #22

Closed colmben closed 6 years ago

colmben commented 6 years ago

Hi,

First off thanks for creating this module, there is a huge gap in the market for a typed, model based resource library, given https://github.com/FineLinePrototyping/angularjs-rails-resource doesn't look like he is going to go to 2+ for his.

I have been playing around with it and have a couple of questions. It may well be that I am just not understanding how the whole thing hangs together and how it should be used. If I end up using the library I'll contribute some doco based on my experiences.

Question 1. I see in your example code that you have a newly created model class instance saving itself like this-

 // Saving the user
  await user.$save();

When I try this, I get a blank request payload send to the server. The same happens if use the resource way of doing (see code below). Am I missing something here? I am assuming $save is provided somehow, but maybe not? Am I supposed to code the save/create behaviour?

**EDIT - almost as soon as I post this, I see the problem for this first question. I was blindly following the example for setting up a resource but this function has an error in it:

$setData(data: IUser): this {
    Object.assign(data);
    this.fullName = `${this.firstName} ${this.lastName}`;
    return this;
  }

should be

$setData(data: IUser): this {
    Object.assign(this, data);
    this.fullName = `${this.firstName} ${this.lastName}`;
    return this;
  }

The same applies to the Group example code obviously.

Generally, if you had any working code from a real project it would be great if you could post it, it really helps when trying to get to grips with a new library like this. END EDIT**

Question 2. I am trying to do a CRUD update on a record. If i retrieve a model instance via GET (which works), change one property and call $update on the instance, it looks OK in my IDE (so the IDE is seeing that $update is a valid method on the model instance), but it then errors in my browser with:

ERROR Error: Uncaught (in promise): TypeError: testClient.$update is not a function

If I do the update via the resource provider it works OK. Is $update on the instance supposed to work?

I am on Angular 5.2, Typescript 2.5.3 and 5.2.9/5.0.1 of resource/core and httpClient handler respectively. Here are some excerpts from my code:

import {ClientResource} from "../model/client/client-resource";
import {Client} from "../model/client/client";
import {UserResource} from "../model/user/user-resource";
import {User} from "../model/user/user";
...
@Component({
  selector: 'app-my-clients',
  templateUrl: './my-clients.component.html',
  styleUrls: ['./my-clients.component.css'],
  providers: [ClientResource]
})
export class MyClientsComponent implements OnInit {
  @Input() user;
  constructor(private clientResource: ClientResource) {
  }

  async ngOnInit() {
    console.log('In myClients, user: ', this.user);
    const myClients: Client[] = await Client.query({search_term: 'M'}); // Works!
    const testClient: Client = await Client.get('18');  // Works!!
    const myUsers: User[] = await User.get(''); // Works, empty quotes needed to do a Collection call
    console.log('In MyClients ngOnInit, testClient : ', testClient);
    console.log('In MyClients ngOnInit, myClients : ', myClients);
    testClient.example = true;
    const newClient = new Client({
      id: 0, // Not clear how to deal with ID on new resource
      assessments_count: 4,
    client_type_id: 2,
    code: 'CNEW',
   example: false,
...
    });
    // newClient.$save() // No request payload
    this.clientResource.create(newClient); // No request payload
    //await testClient.$update(); // Error in browser console
    await this.clientResource.update(testClient); // Works!

  }

}

ClientResource and IClient look like this:

export interface IClientQuery extends IPaginationQuery {
  name?: string;
}

export interface IClient {
  id: number;
  assessments_count: number;
  client_type_id: number;
...
}

@Injectable()
@ResourceParams({
  // IResourceParams
  pathPrefix: '/clients'
})
export class ClientResource extends ResourceCRUD<IClientQuery, Client, Client> {
  constructor(restHandler: ResourceHandler) {
    super(restHandler);
  }
}

and Client looks like this -

import {ResourceModel} from "@ngx-resource/core";
import {ClientResource, IClient} from "./client-resource";

export class Client extends ResourceModel implements IClient {
  readonly $resource = ClientResource;

  id: number;
  assessments_count: number;
  client_type_id: number;
  code: string;
...

  constructor( data?: IClient, ) {
    super();
    if (data) {
      this.$setData(data);
    }
  }

  $setData(data: IClient): this {
    Object.assign(data);
    return this;
  }
}
troyanskiy commented 6 years ago

Hello. First of all thanks for the issue and showing me my error in the example with Object.assign. In your ClientResource, you need to overwrite $resultFactory method so it will create object properly.

export interface IClientQuery extends IPaginationQuery {
  name?: string;
}

export interface IClient {
  id: number;
  assessments_count: number;
  client_type_id: number;
...
}

@Injectable()
@ResourceParams({
  // IResourceParams
  pathPrefix: '/clients'
})
export class ClientResource extends ResourceCRUD<IClientQuery, Client, Client> {
  constructor(restHandler: ResourceHandler) {
    super(restHandler);
  }

  $resultFactory(data: IClient, options?: IResourceActionInner): any {
    return new Client(data);
  }
}
colmben commented 6 years ago

That worked, thanks for the quick response :)