Implementing ChannelAware
Defining channel-aware entities
Making an entity channel-aware means that it can be associated with a specific Channel.
This is useful when you want to have different data or features for different channels. First you will have to create
an entity (Define a database entity) that implements the ChannelAware
interface.
This interface requires the entity to provide a channels
property
import { DeepPartial } from '@vendure/common/lib/shared-types';
import { VendureEntity, Product, EntityId, ID, ChannelAware } from '@vendure/core';
import { Column, Entity, ManyToOne } from 'typeorm';
@Entity()
class ProductRequest extends VendureEntity implements ChannelAware {
constructor(input?: DeepPartial<ProductRequest>) {
super(input);
}
@ManyToOne(type => Product)
product: Product;
@EntityId()
productId: ID;
@Column()
text: string;
@ManyToMany(() => Channel)
@JoinTable()
channels: Channel[];
}
Creating channel-aware entities
Creating a channel-aware entity is similar to creating a regular entity. The only difference is that you need to assign the entity to the current channel.
This can be done by using the ChannelService
which provides the assignToCurrentChannel
helper function.
The assignToCurrentChannel
function will only assign the channels
property of the entity. You will still need to save the entity to the database.
import { ChannelService } from '@vendure/core';
export class RequestService {
constructor(private channelService: ChannelService) {}
async create(ctx: RequestContext, input: CreateRequestInput): Promise<ProductRequest> {
const request = new ProductRequest(input);
// Now we need to assign the request to the current channel (+ default channel)
await this.channelService.assignToCurrentChannel(input, ctx);
return await this.connection.getRepository(ProductRequest).save(request);
}
}
For Translatable entities, the best place to assign the channels is inside the beforeSave
input of the TranslateableSave helper class.
Querying channel-aware entities
When querying channel-aware entities, you can use the ListQueryBuilder or the TransactionalConnection to automatically filter entities based on the provided channel id.
import { ChannelService, ListQueryBuilder, TransactionalConnection } from '@vendure/core';
export class RequestService {
constructor(
private connection: TransactionalConnection,
private listQueryBuilder: ListQueryBuilder,
private channelService: ChannelService) {}
findOne(ctx: RequestContext,
requestId: ID,
relations?: RelationPaths<ProductRequest>) {
return this.connection.findOneInChannel(ctx, ProductRequest, requestId, ctx.channelId, {
relations: unique(effectiveRelations)
});
}
findAll(
ctx: RequestContext,
options?: ProductRequestListOptions,
relations?: RelationPaths<ProductRequest>,
): Promise<PaginatedList<ProductRequest>> {
return this.listQueryBuilder
.build(ProductRequest, options, {
ctx,
relations,
channelId: ctx.channelId,
})
.getManyAndCount()
.then(([items, totalItems]) => {
return {
items,
totalItems,
};
});
}
}