Use ionic directive ion-slides and ion-slide accross different custom component


#1

I am trying ionic2 beta8 and am trying to create a custom component with ion-slide, but I am getting the following error.

 EXCEPTION: Error: Uncaught (in promise): Template parse errors:
    No provider for Slides ("
        [ERROR ->]<ion-slide>
        <ng-content></ng-content>
         </ion-slide>
    "): TaskComponent@1:4
    browser_adapter.js:77 EXCEPTION: Error: Uncaught (in promise): Template parse errors:
    No provider for Slides ("
        [ERROR ->]<ion-slide>
        <ng-content></ng-content>
         </ion-slide>
    "): TaskComponent@1:4

Template:

       <tasks>
             <task>
               <text-step [id]="'step1'" [title]="'Your title here.1'" [text]="'Additional text can go here.'"> </text-step>
               <numeric-step [id]="'step2'" [title]="'Your title here.1'" [text]="23"> </numeric-step>
              </task>
         <task>
               <text-step [id]="'step3'" [title]="'Your title here.1'" [text]="'Additional text can go here.'"> </text-step>
              </task>
              <task>
               <form-step [id]="'step4'" [title]="'Your title here.'" [text]="'Additional text can go here.'"> 
                    <form-item title="Your section title."></form-item>
                    <form-item type="text" id="firstName" text="First Name" placeholder="Mary"></form-item>
                    <form-item type="text" id="lastName" text="Last Name" placeholder="Down"></form-item>
                   </form-step>
              </task>
            </tasks>

TasksComponent

@Component({
    selector: 'tasks',
          directives: [IONIC_DIRECTIVES,TaskComponent,FooterComponent,InstructionStepDirective],
    template: `
       
<ion-slides pager #tasksSlider [options]="tasksOptions" (ionDidChange)="onSlideChanged()" >
    <ng-content></ng-content>
  </ion-slides>
           <footer [tasksSlider]="tasksSlider"></footer>
   
    `,
   providers :[Slides )]
})

export class TasksComponent implements AfterContentInit {
    @ViewChild('tasksSlider') slider: Slides;
 @ContentChildren(TaskComponent)
  task: QueryList<TaskComponent>;
 constructor() {

    }
   // @ContentChildren(TaskComponent) tasks: QueryList<TaskComponent>;
  tasksOptions = {
    initialSlide: 0,
    loop: false
  };

TaskComponent

Injectable()
@Component({
    selector: 'task',
    template: `
    <ion-slide>
    <ng-content></ng-content>
     </ion-slide>
    `,
   directives:  [ IONIC_DIRECTIVES],
   providers :[Slides )]
})
export class TaskComponent {
  
    constructor(@Optional() c: Slides)  {
 
    
    
}
}

How can I use the ionic directive ion slides and ion slide inside two different custom component? Is it possible?


#2

Not sure what exactly causing that error, could be the ) which is inside providers array?


#3

Sorry it was just a copy and paste error, unlucky it is not the reason of the exception


#4

If Slides is a component then it should be inside directives array and not providers. [quote=“mariateresapiselli, post:1, topic:55937”]
directives: [ IONIC_DIRECTIVES],
[/quote]


#5

Sorry, I see it now. You are trying to access the Slides api, my bad. Can you create plunker to illustrate your issue?


#6

Here it is, if you click on thanks button you can see the error on the console.

Thank you for answering


#7

I’m also stuck trying to create a custom component that wraps an ion-slide.

Seems this person is also asking about a similar question: http://stackoverflow.com/questions/37979660/custom-component-with-ion-slide

Anyone seen any progress?


#8

No progress for me.
Anyone can help on this?


#9

Hi, @mariateresapiselli!

I changed your page1.html file to not use your custom components and instead placed ion-slides directly in it. It worked. This means that there is a provider when using in the Page1 component but not in your task custom component.

I think your issue is related with this https://github.com/driftyco/ionic/issues/6531. Your Page1 component has an ion-content in it but your task custom component don’t, so you have a Slides provider when using ion-slides directly in Page1, but not in descendant components. Probably a bug of ionic2, after all, it’s still in beta.

I have a similar issue (related with the link above), where I can use ion-infinite-scroll inside my component pages (they have an ion-content tag), but not inside my custom components (they are modular and don’t have an ion-content tag). Waiting for beta12 to see if this is resolved.


#10

I have the same issue. I’m using the DynamicComponentLoader to add slides. Is there any current workaround? Components get added in ngAfterViewInit() and include ion-slide tags in the component template.

code looks like this atm (slides are added at #extensionAnchor):

<ion-slides [options]="sliderOptions"  #slider>
  <div #extensionAnchor></div>
</ion-slides>

#11

I went into ionic-angular/components/slides/slides.js and added providers: [Slides] to the Slide.decorators property. The error goes away, but the slides are not rendered properly (all of the content is visible on a single slide). I’m not sure if I’m going to be able to figure this out, but this is the direction I’m looking into.

Slide.decorators = [
    { type: Component, args: [{
                selector: 'ion-slide',
                template: '<div class="slide-zoom"><ng-content></ng-content></div>',
                changeDetection: ChangeDetectionStrategy.OnPush,
                encapsulation: ViewEncapsulation.None,
                providers: [Slides]
            },] },

#12

Looking at the code more, it looks like each individual slide requires a reference to a slides object (obviously this is supposed to be the one they are a part of). So it may not be possible to use ion-slide on its own in a template. We may be better off for now making our own version of Slide rather than building a component around it?

E.g. In your example the only difference I see is that you want to use task as the selector, so you could make your own with:

Slide.decorators = [
    { type: Component, args: [{
                selector: 'task',
                template: '<div class="slide-zoom"><ng-content></ng-content></div>',
                changeDetection: ChangeDetectionStrategy.OnPush,
                encapsulation: ViewEncapsulation.None
            },] },

#13

I made some progress modifying the ionic slides code to allow custom ion-slide wrappers, but it wasn’t going to worth compared to just writing your own Slide component directly.

I wrote a lengthy SO answer here. I think the best solution is to write your component to replace ion-slide rather than to wrap it. The typescript version of your custom task would be

import { Slides } from 'ionic-angular';

@Component({
  selector: 'task',
  template: '<div class="slide-zoom"><ng-content></ng-content></div>',
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
})
export class Task {
  @Input() zoom: any;
  
  constructor(elementRef: ElementRef, @Host() public slides: Slides) {
    elementRef.nativeElement.classList.add('swiper-slide');
    slides.rapidUpdate();
  }

  ngOnDestroy() {
    this.slides.rapidUpdate();
  } 
}

I included a possible better solution in my linked answer that uses a decorator for extending a component. Your task using this CustomComponent decorator this would be:

import { Slides } from 'ionic-angular';

@CustomComponent({
  selector: 'task',
  template: '<div class="slide-zoom"><ng-content></ng-content></div>',
})
export class Task extends Slide {
}

Custom ion-slide component