我正在尝试使用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>
@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
答案 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
我玩弄了这个,你可以让它像这样工作:
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');
}
}
的功能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