将自定义组件与 Angular2 一起使用时,JQueryUI Sortable 不起作用
JQueryUI Sortable not working when using custom component with Angular2
我的目标是能够让用户对命令列表进行排序。我正在使用 Angular2/Typescript.
开发我的应用程序
所以我四处寻找基于 angular2 的库,这些库可能提供类似于 JQueryUI Sortable 的可排序功能,但找不到太多。
我遇到了 this SO post, which demonstrated how to integrate JQuery with angular2. Using the plunk provided in one of the solutions for this post, I could develop a sortable behavior with angular2. See this plunk。这按预期工作。
@Component({
selector: 'my-app',
directives: [SMSortable],
providers: [],
template: `
<div>
<p>This is a list that can be sorted </p>
<div sm-sortable>
<p>Item 1</p>
<p>Item 2</p>
<p>Item 3</p>
</div>
</div>
`
})
export class App {
constructor() {
this.name = 'Angular2'
}
}
我们的想法是定义一个指令,使用 JQueryUI sortable() API 将可排序行为应用于本机元素。然后使用组件模板中的指令。
@Directive({
selector: "[sm-sortable]"
})
export class SMSortable{
constructor(el: ElementRef) {
jQuery(el.nativeElement).sortable( {
start: function(event, ui) {
console.log("Old position: " + ui.item.index());
},
stop: function(event, ui) {
console.log("New position: " + ui.item.index());
}
});
}
}
当组件的模板包含所有本机元素时,这很有效。但是如果我的模板有自定义的 angular2 组件,这将停止工作。
看到这个not-working plunk。
@Component ({
selector: 'sm-cmd',
template: '<ng-content></ng-content>'
})
export class SMCommand {
}
@Component({
selector: 'my-app',
directives: [SMSortable, SMCommand],
providers: [],
template: `
<div>
<p>This is a list that can be sorted </p>
<div sm-sortable>
<sm-cmd><p>Item 1</p></sm-cmd>
<sm-cmd><p>Item 2</p></sm-cmd>
<sm-cmd><p>Item 3</p></sm-cmd>
</div>
</div>
`
})
export class App {
}
在这种情况下,我可以拖动项目,但不能放下它。移动的项目恢复到其原始位置。我添加了 console.log 以在排序期间查看开始和停止事件的项目索引。该值保持不变。
我无法对此进行进一步调试。有人可以提供一些意见吗?
问题实际上很简单:由于您使用的是自定义元素 sm-cmd
浏览器不知道要使用什么渲染模型(块或内联)。默认情况下,它应用内联一,这会导致元素尺寸方面的冲突,因为内联 sm-cmd
内有块级 p
。因此浏览器无法正确计算块尺寸。
所以解决方案就是这个简单的 CSS 规则:
sm-cmd {display: block;}
还要确保在 ngAfterViewInit 挂钩中初始化 jQuery 插件:
@Directive({
selector: "[sm-sortable]"
})
export class SMSortable{
constructor(private el: ElementRef) {}
ngAfterViewInit() {
jQuery(this.el.nativeElement).sortable( {
start: function(event, ui) {
console.log("Old position: " + ui.item.index());
},
stop: function(event, ui) {
console.log("New position: " + ui.item.index());
}
});
}
}
我的目标是能够让用户对命令列表进行排序。我正在使用 Angular2/Typescript.
开发我的应用程序所以我四处寻找基于 angular2 的库,这些库可能提供类似于 JQueryUI Sortable 的可排序功能,但找不到太多。
我遇到了 this SO post, which demonstrated how to integrate JQuery with angular2. Using the plunk provided in one of the solutions for this post, I could develop a sortable behavior with angular2. See this plunk。这按预期工作。
@Component({
selector: 'my-app',
directives: [SMSortable],
providers: [],
template: `
<div>
<p>This is a list that can be sorted </p>
<div sm-sortable>
<p>Item 1</p>
<p>Item 2</p>
<p>Item 3</p>
</div>
</div>
`
})
export class App {
constructor() {
this.name = 'Angular2'
}
}
我们的想法是定义一个指令,使用 JQueryUI sortable() API 将可排序行为应用于本机元素。然后使用组件模板中的指令。
@Directive({
selector: "[sm-sortable]"
})
export class SMSortable{
constructor(el: ElementRef) {
jQuery(el.nativeElement).sortable( {
start: function(event, ui) {
console.log("Old position: " + ui.item.index());
},
stop: function(event, ui) {
console.log("New position: " + ui.item.index());
}
});
}
}
当组件的模板包含所有本机元素时,这很有效。但是如果我的模板有自定义的 angular2 组件,这将停止工作。
看到这个not-working plunk。
@Component ({
selector: 'sm-cmd',
template: '<ng-content></ng-content>'
})
export class SMCommand {
}
@Component({
selector: 'my-app',
directives: [SMSortable, SMCommand],
providers: [],
template: `
<div>
<p>This is a list that can be sorted </p>
<div sm-sortable>
<sm-cmd><p>Item 1</p></sm-cmd>
<sm-cmd><p>Item 2</p></sm-cmd>
<sm-cmd><p>Item 3</p></sm-cmd>
</div>
</div>
`
})
export class App {
}
在这种情况下,我可以拖动项目,但不能放下它。移动的项目恢复到其原始位置。我添加了 console.log 以在排序期间查看开始和停止事件的项目索引。该值保持不变。
我无法对此进行进一步调试。有人可以提供一些意见吗?
问题实际上很简单:由于您使用的是自定义元素 sm-cmd
浏览器不知道要使用什么渲染模型(块或内联)。默认情况下,它应用内联一,这会导致元素尺寸方面的冲突,因为内联 sm-cmd
内有块级 p
。因此浏览器无法正确计算块尺寸。
所以解决方案就是这个简单的 CSS 规则:
sm-cmd {display: block;}
还要确保在 ngAfterViewInit 挂钩中初始化 jQuery 插件:
@Directive({
selector: "[sm-sortable]"
})
export class SMSortable{
constructor(private el: ElementRef) {}
ngAfterViewInit() {
jQuery(this.el.nativeElement).sortable( {
start: function(event, ui) {
console.log("Old position: " + ui.item.index());
},
stop: function(event, ui) {
console.log("New position: " + ui.item.index());
}
});
}
}