6

I need to access the model by the html element in angular2. In my case I use ng2-dragula to perform drag and drop and its service only has access to the html elements that are dragged. And I need to update the corresponding model of the element. Heres the issue at github.

4
  • 1
    By "model of the element" do you mean some component's properties? Some code would help (Plunker preferred). Commented Apr 15, 2016 at 15:30
  • @MarkRajcok The code is at github, the link is in the end of the question. I meant angular2 model that makes this element appear. Let me know if its not clear after checking the code. Commented Apr 16, 2016 at 20:37
  • I'm not aware of any way to go "from HTML element to component" -- i.e., given an HTML, I don't know how to get a reference to the component where that HTML element is used... the component whose template has that HTML element. Commented Apr 18, 2016 at 14:26
  • Seems there should be a dirty way of using the ng.probe(htmlElement), but its used for debug purposes only. So for now its like "it can be done", didnt check how ng.probe works under the hood. Commented Dec 29, 2016 at 10:59

3 Answers 3

2

You can get the model of your item by searching for the index of the element in the elementList provided by the arguments of the subscription.

dragulaService.drop.subscribe(e => this.onDrop(e.slice(1)));

See?

UPDATE: Simplification (Thanks to Dracco)

private onDrop(args) {

    let [e, el] = args; //element, elementList
    let i = el.children.indexOf(e),
    item = i+1? this.items[i] : null;

    console.log(item); //The item
}

this.items is the variable where you store the list you pass to dragula. (e.g: [dragulaModel]="items").

I wish there was a simpler way. Tell me if you find one!

Old way:

private onDrop(args) {

    let [e, el] = args; //element, elementList
    let item;
    for(let i in el.children){
        if(el.children[i]==e){
            item = this.items[+i];
            break;                
        }
    }

    console.log(item); //The item
}

EDIT: the simplification had an error.

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

4 Comments

Simpler form of the same way: use indexOf developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
I am unable to get the model from this. Only references to html elements
Sorry, The simplied form had an error. I fixed it now.
@yaroslav-yakovlev Did you find my answer useful? If so, could you please accept it as the correct answer?
0

If your ngFor is compiled from an array, you need to provide model by setting the dragulaModel attribute on the bag element.

<ul [dragula]='"bag-one"' [dragulaModel]='items'> <li *ngFor="let item of items"></li> </ul>

And whenever you re-position the items, the model will be synced. In your component, you can easily get the updated model by doing this.

this.dragulaService.drop.subscribe((value) => {
        //let [bagName, e, el] = value;
        console.log(this.items);
    });

You will notice that the items are re-positioned in your model.

1 Comment

Is there no way to univocally tell which item is being moved?
0

Make sure to wrap el.children in a ES6 Array.

let i = el.children.indexOf(e)

Should be

let i = Array.from(el.children).indexOf(e)

I also found that retrieving the child element with the index from the parent list produced unpredictable results and sometimes generated new undefined items.

Alternative Direct ID Solution:

<ion-item *ngFor="let child of children" [id]="child"></ion-item>

and then in the onDrop method

console.log(e.id);

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.