4

My aim is to be able to allow users to sort a list of commands. I am developing my application using Angular2/Typescript.

So I looked around for angular2 based libraries that may provide sortable functionality similar to JQueryUI Sortable, But couldn't find much.

I came across 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. This is working as expected.

@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'
  }
}

The idea was to define a directive which would apply the sortable behavior to the native element using JQueryUI sortable() API. And then use the directive in the component's template.

@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());
              }
        });
    }
}

This works well when the component's template has all native elements. But if my template has custom angular2 components, this stops working.

See this 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 {

}

In this case I am able to drag the item, but not able to drop it. The moved item reverts back to its original location. I added console.log to see the item index at start and stop event during sort. The value remains same.

I am not able to debug further on this. Could somebody provide some input on this?

7
  • Post non-working plunkr. Commented Mar 23, 2016 at 7:49
  • not-working plunker actually is working - wrong link? Commented Mar 23, 2016 at 7:49
  • Yes non working is working in fact. Commented Mar 23, 2016 at 7:50
  • Strange, its not working when I run this plunk. plnkr.co/edit/tqddjpLzVdrA4GvjhUw4?p=preview Commented Mar 23, 2016 at 7:53
  • Which browser? I am with chrome 49. Commented Mar 23, 2016 at 7:54

1 Answer 1

5

The problem is actually very simple: since you are using custom element sm-cmd browser doesn't know what rendering-model to use (block or inline). By default it applies inline one, which results into a collision in terms of element dimensions, because you have block-level p inside inline sm-cmd. So the browser doesn't calculate block dimensions properly.

So the solution is this simple CSS rule:

sm-cmd {display: block;}

Also make sure you initialize jQuery plugin in ngAfterViewInit hook:

@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());
            }
      });
  }
}

Demo: http://plnkr.co/edit/QEd9wozXSZlqT07qr51h?p=preview

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.