diff --git a/projects/angular2-jsonapi/src/services/json-api-datastore.service.spec.ts b/projects/angular2-jsonapi/src/services/json-api-datastore.service.spec.ts index eb896011..d2bca622 100644 --- a/projects/angular2-jsonapi/src/services/json-api-datastore.service.spec.ts +++ b/projects/angular2-jsonapi/src/services/json-api-datastore.service.spec.ts @@ -3,7 +3,7 @@ import { parseISO } from 'date-fns'; import { Author } from '../../test/models/author.model'; import { Chapter } from '../../test/models/chapter.model'; import { AUTHOR_API_VERSION, AUTHOR_MODEL_ENDPOINT_URL, CustomAuthor } from '../../test/models/custom-author.model'; -import { AUTHOR_BIRTH, AUTHOR_ID, AUTHOR_NAME, BOOK_TITLE, getAuthorData } from '../../test/fixtures/author.fixture'; +import { AUTHOR_BIRTH, AUTHOR_ID, AUTHOR_NAME, BOOK_TITLE, getAuthorData, getIncludedBooks } from '../../test/fixtures/author.fixture'; import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; import { API_VERSION, BASE_URL, Datastore } from '../../test/datastore.service'; import { ErrorResponse } from '../models/error-response.model'; @@ -695,5 +695,32 @@ describe('JsonApiDatastore', () => { saveRequest.flush({}); }); + + it('should remove empty BelongsTo-relationship', () => { + const BOOK_NUMBER = 2; + const DATA = getAuthorData('books', BOOK_NUMBER); + const author = new Author(datastore, DATA); + author.syncRelationships(DATA, getIncludedBooks(BOOK_NUMBER, 'books.category')); + + expect(author.books).toBeDefined(); + expect(author.books.length).toBe(BOOK_NUMBER); + + const firstBook = author.books[0]; + expect(firstBook.category).toBeDefined(); + expect(firstBook.category.name).toBeDefined(); + + const expectedUrl = `${BASE_URL}/${API_VERSION}/books/${firstBook.id}`; + + firstBook.category = null; + firstBook.save().subscribe(); + + const saveRequest = httpMock.expectOne({method: 'PATCH', url: expectedUrl}); + const obj = saveRequest.request.body.data; + expect(obj.relationships).toBeDefined(); + expect(obj.relationships.category).toBeDefined(); + expect(obj.relationships.category.data).toBeNull(); + + saveRequest.flush({}); + }); }); }); diff --git a/projects/angular2-jsonapi/src/services/json-api-datastore.service.ts b/projects/angular2-jsonapi/src/services/json-api-datastore.service.ts index 01d26259..61990759 100644 --- a/projects/angular2-jsonapi/src/services/json-api-datastore.service.ts +++ b/projects/angular2-jsonapi/src/services/json-api-datastore.service.ts @@ -1,16 +1,18 @@ import { Injectable } from '@angular/core'; import { HttpClient, HttpErrorResponse, HttpHeaders, HttpResponse } from '@angular/common/http'; -import { find } from 'lodash-es'; -import { catchError, map } from 'rxjs/operators'; import { Observable, of, throwError } from 'rxjs'; +import { catchError, map } from 'rxjs/operators'; + +import { find } from 'lodash-es'; +import * as qs from 'qs'; +import 'reflect-metadata'; + import { JsonApiModel } from '../models/json-api.model'; import { ErrorResponse } from '../models/error-response.model'; import { JsonApiQueryData } from '../models/json-api-query-data'; -import * as qs from 'qs'; import { DatastoreConfig } from '../interfaces/datastore-config.interface'; import { ModelConfig } from '../interfaces/model-config.interface'; import { AttributeMetadata } from '../constants/symbols'; -import 'reflect-metadata'; export type ModelType = new(datastore: JsonApiDatastore, data: any) => T; @@ -287,6 +289,15 @@ export class JsonApiDatastore { data: relationshipData }; } + } else if (data[key] === null) { + const entity = belongsToMetadata.find((it: any) => it.propertyName === key); + if (entity) { + relationships = relationships || {}; + const relationshipKey = entity.relationship; + relationships[relationshipKey] = { + data: null + }; + } } } } @@ -461,6 +472,10 @@ export class JsonApiDatastore { for (const relationship in relationships) { if (relationships.hasOwnProperty(relationship) && model.hasOwnProperty(relationship)) { const relationshipModel: JsonApiModel = model[relationship]; + if (relationshipModel === null) { + continue; + } + const hasMany: any[] = Reflect.getMetadata('HasMany', relationshipModel); const propertyHasMany: any = find(hasMany, (property) => { return modelsTypes[property.relationship] === model.constructor;