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.
-
1By "model of the element" do you mean some component's properties? Some code would help (Plunker preferred).Mark Rajcok– Mark Rajcok2016-04-15 15:30:39 +00:00Commented 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.Yaroslav Yakovlev– Yaroslav Yakovlev2016-04-16 20:37:45 +00:00Commented 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.Mark Rajcok– Mark Rajcok2016-04-18 14:26:57 +00:00Commented 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.Yaroslav Yakovlev– Yaroslav Yakovlev2016-12-29 10:59:14 +00:00Commented Dec 29, 2016 at 10:59
3 Answers
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.
4 Comments
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
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);