JQueryUI Sortable не работает при использовании пользовательского компонента с Angular2
Моя цель - позволить пользователям сортировать список команд. Я разрабатываю свое приложение, используя Angular2/Typescript.
Поэтому я искал библиотеки на основе angular2, которые могут обеспечить сортируемую функциональность, аналогичную JQueryUI Sortable, но не смогли найти много.
Я наткнулся на этот пост, который демонстрировал, как интегрировать JQuery с angular2. Используя планку, предоставленную в одном из решений для этого поста, я мог разработать сортируемое поведение с angular2. Посмотри на это. Это работает, как ожидалось.
@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'
}
}
Идея состояла в том, чтобы определить директиву, которая применила бы сортируемое поведение к нативному элементу с помощью API JQueryUI sortable (). А затем используйте директиву в шаблоне компонента.
@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, это перестает работать.
Вижу этот неработающий отврат.
@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, чтобы увидеть индекс элемента при запуске и остановку события во время сортировки. Значение остается тем же.
Я не могу дальше отлаживать это. Может ли кто-нибудь внести свой вклад в это?
1 ответ
Проблема на самом деле очень проста: поскольку вы используете пользовательский элемент sm-cmd
браузер не знает, какую модель рендеринга использовать (блочную или встроенную). По умолчанию применяется встроенный, что приводит к коллизии с точки зрения размеров элемента, потому что у вас есть уровень блока p
внутри встроенный sm-cmd
, Таким образом, браузер не рассчитывает размеры блока правильно.
Итак, решение - это простое правило CSS:
sm-cmd {display: block;}
Также убедитесь, что вы инициализируете плагин jQuery в хуке ngAfterViewInit:
@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());
}
});
}
}
Демонстрация: http://plnkr.co/edit/QEd9wozXSZlqT07qr51h?p=preview