0
votes

Getting below error when compiling new custom paragraph component

** ERROR in src/app/custom-page/new-para/new-para.component.html:7:12 - error TS2769: No overload matches this call. The last overload gave the following error. Argument of type 'CmsComponentData' is not assignable to parameter of type 'Promise'. Type 'CmsComponentData' is missing the following properties from type 'Promise': then, catch, [Symbol.toStringTag], finally

7 <p *ngIf="(cmsComponent | async)?.data as data" [innerHTML]="data.content">

~~~~~~~~~

src/app/custom-page/new-para/new-para.component.ts:8:16 8 templateUrl: './new-para.component.html', ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Error occurs in the template of component NewParaComponent.

**

files used:

"new-para.component.ts"

import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
import { Observable } from 'rxjs';
import { PromotionResult, CmsService, CmsParagraphComponent } from '@spartacus/core';
import { PromotionService, CmsComponentData } from '@spartacus/storefront';

@Component({
  selector: 'app-new-para',
  templateUrl: './new-para.component.html',
  styleUrls: ['./new-para.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})

export class NewParaComponent {

  cartPromotion$: Observable<PromotionResult[]> = this.promotionService.getOrderPromotionsFromCart();
  
  cmsComponent: CmsParagraphComponent;
  
  constructor(protected promotionService: PromotionService, 
    public component: CmsComponentData<CmsParagraphComponent>, 
    public cmsService: CmsService) { }

}

"new-para.component.html"

<p *ngIf="(cmsComponent | async) as data" [innerHTML]="data.name"></p>

"custom-page.module.ts"

ConfigModule.withConfig({
      cmsComponents: {
        CMSParagraphComponent: {
          component: NewParaComponent,
        }
      }

new console error after trying both options:

core.js:6228 ERROR Error: Uncaught (in promise): NullInjectorError: R3InjectorError(AppModule)[CmsComponentData -> CmsComponentData -> CmsComponentData]: 
  NullInjectorError: No provider for CmsComponentData!
NullInjectorError: R3InjectorError(AppModule)[CmsComponentData -> CmsComponentData -> CmsComponentData]: 
  NullInjectorError: No provider for CmsComponentData!
    at NullInjector.get (core.js:1085)
    at R3Injector.get (core.js:16955)
    at R3Injector.get (core.js:16955)
    at R3Injector.get (core.js:16955)
    at NgModuleRef$1.get (core.js:36329)
    at Object.get (core.js:33972)
    at getOrCreateInjectable (core.js:5848)
    at Module.ɵɵdirectiveInject (core.js:21103)
    at NodeInjectorFactory.NewParaComponent_Factory [as factory] (new-para.component.ts:12)
1
It would be helpful if you can post the component controller implementation, you'll get more valuable feedback. - tobi-or-not-tobi
brtw, the typescript compiler complains about your code. If you use an IDE that compiles typescript, you should get errors during development. I'd recommend vscode. - tobi-or-not-tobi
i have updated my questions with code used, also there are no error in transcripts files, it gets compiled properly but then after compilation error comes in .html file - Naman

1 Answers

0
votes

Thanks for posting the code snippets, that helps. Based on the error it looks like the code is missing a few bits and pieces, but I get the idea.

Here's what you should do:

Option 1

  • make the component constructor arguments private or protected as you don't use it in the template
  • Assign the data$ property from the component.data$ to the property cmsComponent. You can do this directly when creating the property or during het oninit lifecycle hook
  • Observe the data$ property
component$: Observable<CmsParagraphComponent> = this.component.data$;
  
constructor(protected component: CmsComponentData<CmsParagraphComponent>) { }
<p *ngIf="(component$ | async) as data" [innerHTML]="data.name"></p>

Option 2

  • Use the public service directly in the html
  • Bind to the data$ property of the service
constructor(public component: CmsComponentData<CmsParagraphComponent>) { }
<p *ngIf="(component.data$ | async) as data" [innerHTML]="data.name"></p>

While option 2 is shorter, I prefer option 1. It scales better, in case you need to operate on the data stream and bring other streams into the mix.