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 Apr 15 '16 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 Apr 16 '16 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 Apr 18 '16 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 Dec 29 '16 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.
- 483
- 4
- 15
-
1Simpler form of the same way: use indexOf https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf – Dracco Mar 13 '17 at 12:13
-
I am unable to get the model from this. Only references to html elements – Trevor de Koekkoek Nov 16 '17 at 23:38
-
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,409
- 1
- 12
- 16
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);
- 21
- 5