具有离子滑动的自定义组件

时间:2016-06-22 23:08:06

标签: ionic2

我正在尝试使用ionic2 beta9并尝试使用离子幻灯片创建自定义组件,但我收到了错误消息。

父组件

<ion-content class="home" padding>    
  <ion-slides loop="true">
    <slide-item *ngFor="let image of [1,2,3,4,5]" [imgIdx]="image"></slide-item>
  </ion-slides>
</ion-content>

幻灯片项自定义组件

<ion-slide>
        <div class="bcontent">
            <div class="bimg">
                <img data-src="images/slide{{imgIdx}}.jpeg">
            </div>
            <p class="info">My text</p>
        </div>
</ion-slide>

滑动item.ts

@Component({
  selector: 'slide-item',
  templateUrl: 'build/components/slide-item/slide-item.html',
  directives: [Slides, Slide]
})
export class SlideItem {

  @Input()
  imgIdx: number;

  constructor() {
    console.log("SlideItem::constructor...imgIdx="+this.imgIdx);
  }
}

我收到以下错误:

zone.js:461

Unhandled Promise rejection: Template parse errors:
No provider for Slides ("
  for more info on Angular 2 Components.
-->
[ERROR ->]<ion-slide>
        <div class="bcontent">
            <div class="bimg">
"): SlideItem@6:0 

区域:角;任务:Promise.then;价值:

BaseException {message: "Template parse errors:↵No provider for Slides ("↵ …↵            <div class="bimg">↵"): 
SlideItem@6:0", stack: "Error: Template parse errors:↵No provider for Slid…ndroid_asset/www/build/js/app.bundle.js:30622:41)"}message: 
"Template parse errors:↵No provider for Slides ("↵  for more info on Angular 2 Components.↵-->↵[ERROR ->]<ion-slide>↵        <div class="bcontent">↵            <div class="bimg">↵"): SlideItem@6:0"

stack: "Error: Template parse errors:↵No provider for Slides ("↵  for more info on Angular 2 Components.↵-->↵[ERROR ->]<ion-slide>↵        <div class="bcontent">↵            <div class="bimg">↵"): SlideItem@6:0↵    at new BaseException (file:///android_asset/www/build/js/app.bundle.js:1760:23)↵    at TemplateParser.parse (file:///android_asset/www/build/js/app.bundle.js:16401:19)↵    at file:///android_asset/www/build/js/app.bundle.js:14643:64↵    at ZoneDelegate.invoke (file:///android_asset/www/build/js/zone.js:323:29)↵    at Object.onInvoke (file:///android_asset/www/build/js/app.bundle.js:30631:41)↵    at ZoneDelegate.invoke (file:///android_asset/www/build/js/zone.js:322:35)↵    at Zone.run (file:///android_asset/www/build/js/zone.js:216:44)↵    at file:///android_asset/www/build/js/zone.js:571:58↵    at ZoneDelegate.invokeTask (file:///android_asset/www/build/js/zone.js:356:38)↵    at Object.onInvokeTask (file:///android_asset/www/build/js/app.bundle.js:30622:41)"__proto__: ErrorconsoleError @ zone.js:461_loop_1 @ zone.js:490drainMicroTaskQueue @ zone.js:494ZoneTask.invoke @ zone.js:426

1 个答案:

答案 0 :(得分:0)

为什么不起作用

我不认为幻灯片和幻灯片组件的当前设计是可行的。 ion-slide必须是ion-slides元素的子元素,并且必须能够在同一模板中找到其父幻灯片

这是来源:

@Component({
  selector: 'ion-slide',
  template: '<div class="slide-zoom"><ng-content></ng-content></div>',
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
})
export class Slide {

  ele: HTMLElement;

  @Input() zoom: any;

  constructor(
    elementRef: ElementRef,
    @Host() public slides: Slides
  ) {
    this.ele = elementRef.nativeElement;
    this.ele.classList.add('swiper-slide');

    slides.rapidUpdate();
  }

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

您可以看到父Slides是必需的,以便Slide可以在动态添加或销毁某个Slides时触发@Host更新。它仅限于使用ion-slide装饰器的当前模板。

当您尝试在自定义模板中使用Slides时出现模板错误,因为模板中没有Slide个对象要传递给slides

One Partial-Solution

我玩弄了这个,你可以让它像这样工作:

  1. 删除引用Slides到父Slides个对象,牺牲了动态添加/删除幻灯片时自动更新@Component({ selector: 'ion-slide', template: '<div class="slide-zoom"><ng-content></ng-content></div>', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, }) export class Slide { ele: HTMLElement; @Input() zoom: any; constructor( elementRef: ElementRef ) { this.ele = elementRef.nativeElement; this.ele.classList.add('swiper-slide'); } } 的功能
  2. 将“幻灯片缩放”类添加到自定义幻灯片中。
  3. slide.ts修改后的来源:

    @Component({
      selector: 'slide-item',
      templateUrl: 'slide-item.html',
    })
    export class SlideItem {
    
      @Input()
      imgIdx: number;
    
      constructor(elementRef: ElementRef) {
        console.log("SlideItem::constructor...imgIdx="+this.imgIdx);
        elementRef.nativeElement.classList.add('swiper-slide');
      }
    }
    

    您的幻灯片项目:

    Slides

    我说这是部分解决方案,因为您必须修改离子源,因为现在您必须在添加/删除幻灯片时手动调用更新Slide更新。< / p>

    我确实在进一步修改离子源方面取得了一些进展,以便在添加/删除幻灯片(包括您自己的自定义幻灯片容器)时保持自动更新。但与下面的选项相比,它看起来并不值得。

    部分解决方案2

    ion-slide的代码非常简单。你最好的选择可能只是直接定义你自己的组件(而不是包装@Component({ selector: 'slide-item', templateURL: 'slite-item.html', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, }) export class SlideItem { ele: HTMLElement; @Input() zoom: any; @Input() imgIdx: number; constructor( elementRef: ElementRef ) { this.ele = elementRef.nativeElement; this.ele.classList.add('swiper-slide'); console.log("SlideItem::constructor...imgIdx="+this.imgIdx) } } ):

    <div class="slide-zoom bcontent">
      <div class="bimg">
        <img data-src="images/slide{{imgIdx}}.jpeg">
      </div>
      <p class="info">My text</p>
    </div>
    

    和模板

    ComponentMetaData

    我将这个称为部分解决方案,因为你必须保留一些反映离子的额外来源。如果离子载玻片实施发生变化,您可能需要更新自定义幻灯片。

    改进的解决方案

    Here is a SO answer about extending a component。我没有得到这个工作,因为到目前为止它不是最新的Angular(Slide不再存在),但我认为这是一个更好的方法。您将使用此装饰器导入和扩展export function CustomComponent(annotation: any) { return function (target: Function) { var parentTarget = Object.getPrototypeOf(target.prototype).constructor; var parentAnnotations = Reflect.getMetadata('annotations', parentTarget); var parentAnnotation = parentAnnotations[0]; Object.keys(parentAnnotation).forEach(key => { if (isPresent(parentAnnotation[key])) { annotation[key] = parentAnnotation[key]; } }); var metadata = new ComponentMetadata(annotation); Reflect.defineMetadata('annotations', [ metadata ], target); } } 组件。

    import { Slide } from 'ionic-angular';
    
    @CustomComponent({
      selector: 'slide-item',
      templateURL: 'slite-item.html'
    })
    export class SlideItem extends Slide {
      @Input() imgIdx: number;
    }
    

    您的模板将与之前的解决方案相同,但课程简化为以下内容。

        int? length = customers?.Length; // null if customers is null   
        Customer first = customers?[0];  // null if customers is null  
        int? count = customers?[0]?.Orders?.Count();  // null if customers, the first         customer, or Orders is null