vue.js vue-grid-layout exchange widgets by drag and drop - vue.js

I use vue.js now for about a month and wanted to use the vue-grid-layout to build up a grid 8x4. Is there a possibility to exchange the widgets by each other or is it only possible to put it in between and push it to the bottom?
Example by dragging c to a:
a b c d
gets
c b d
a
But what I want to achieve is:
a b c d
gets
c b a d
What is the best way to implement such a behavior?
Do I have to use a different grid engine?
if so, which one would you prefer?
Thx in advance
Pedy

In order to achieve this effect, you are going to have to orchestrate several events on several components, and signal from the children to the parent when certian things happen.
We have 2 components involved in this operation - the parent component and the draggable child component (which has multiple instances). In the parents template we have the following...
<div id="dropTargetDiv" #drop.prevent="drop" v-on:startIndex="setStartIndex(value)" v-on:targetIndex="setTargetIndex(value)">
<draggable-component v-for="(itemData, index) in dataArray" :itemData="itemData" index="index"/>
</div>
The parent also has these methods...
setStartIndex(value) {
this.startIndex = value;
},
setTargetIndex(value) {
this.targetIndex = value;
},
drop(event) {
this.swapElements(this.startIndex, this.targetIndex);
},
swapElements(start, target) {
// Clone the original array
var newArray = JSON.parse(JSON.stringify(this.dataArray));
// Swap elements
var startElement = newArray[start];
var targetElement = newArray[target];
newArray[target] = startElement;
newArray[start] = targetElement;
// Update the UI
this.dataArray = newArray;
}
In the child component, on its root element, we have the following...
<div class="draggableItem" draggable="true" #dragstart="$emit('startIndex', this.index)" #dragenter.prevent="$emit('targetIndex', this.index)">
If you see that the target index isn't being set correctly, you may want to replace the #dragenter.prevent with #dragover.prevent.
This should work - comments are welcome. You will need to drop on top of another child, not between them.

Related

MatPagination: mat-table does not update item limit when changing MatPaginator

I am trying to paginate my table.
I have the full implementation of Angular Material Table with Pagination(https://material.angular.io/components/table/overview#pagination)
Since I am using Angularfire2 my dataSource is an Observable.
this.items = this.itemsCollection.valueChanges();
I read that I have to use
dataSource = new MatTableDataSource<Item>;
to create a working connection between table and paginator.
I populate the dataSource by
let subscription = this.items.subscribe(
newData => { this.dataSource.data = newData });
and update the dataSource's paginator by
ngAfterViewInit() {
this.dataSource.paginator = this.paginator;
}
where this.paginator is defined by
#ViewChild(MatPaginator) paginator: MatPaginator
like explained in Angular Material's components doc.
The paginator(mat-paginator) is working fine. However, my issue is that the table does not refresh and continues to show all values. Initial values to 'this.paginator' are also not passed to the table limit.
I found a known bug, but I am not sure if that applies to my problem...
Can anyone help me out?
Thank you in advanced!!
Update
I found an easy solution for my problem by using the Angular Pipe at mat-table. I added the slice pipe like this:
<mat-table #table [dataSource]="dataObservable | async | slice: a:b">
and in my data component I was listening to the change event of the HTML Element "mat-paginator"
(page)="changePage($event)"
In my component I can easily set the sliced data
a = 0;
b = this.limit;
changePage(ev) {
console.log( ev );
this.a = ev.pageIndex * ev.pageSize;
this.b = this.a + ev.pageSize;
console.log(this.a);
console.log(this.b);
}

Disabling/enabling buttons by data in Vue.js?

I'm having a look at Vue.js with a view to simplifying an application which is starting to get a bit too complex with jQuery. I want to utilise the data binding so that the state of an 'Order' object automatically enables or disables certain buttons (e.g., I want the submit button to be automatically disabled unless an order, containing items, exists). I have something which partly works, with this declaration:
var content = new Vue({
el: '#content',
computed: {
orderExists: function () {
return (shopOrder != null && !isEmpty(shopOrder.items));
}
}
});
I use it in a button like this:
<button type="button" id="btnDisplay" v-bind:disabled="!orderExists">Show Selected</button>
On page load, the buttons using this technique are indeed enabled/disabled correctly. However, when I add items to the order object, thereby changing its state, I'm not seeing any update in the buttons' states - they should be being enabled.
I assume I'm misunderstanding something basic about how this works with Vue.js, as I've only spent a couple of hours with it, so any help would be appreciated.
Hmmm why not pass the property as reactive data?
You can do something like:
...
computed: {
orderExists: function () {
this.disabled = (shopOrder != null && !isEmpty(shopOrder.items));
}
}
Fiddle.
DP: the example is in Vue 2
The issue is that Vue has to manage your data objects in order to set them up in a way where it can observe the changes to them (i.e. be made reactive). This is done by specifying the data option to your Vue creation. Something like:
data: {
shopOrder: null
}
Then update your code like this:
orderExists: function () {
return (this.shopOrder != null && !isEmpty(this.shopOrder.items));
}
And of course at some point you need to set this.shopOrder to a valid order object.

Sharing information between Polymer 1.0 modules

I have two components inside a parent, one component shows me a list, and I want the other component to show me the details of an item of the list. I'm using the List of this demo https://elements.polymer-project.org/elements/neon-animation?view=demo:demo/index.html&active=neon-animated-pages
since I have these two components
<list-view data="[[fileData]]" on-item-click="_onItemClick"></list-view>
<full-view on-close="_onClose"></full-view>
I would like to pass the Id of an item clicked on list-view to the full-view. So what would be the best way to execute an event on "full-view" when an item of "list-view" is clicked? I need to pass information from list-view to full-view.
Thank you.
What about of databinding? #SG_ answer is ok, but it can does using simple databinding, as follows:
<list-view data="[[fileData]]" on-item-click="_onItemClick" selected-id="{{idSelected}}"></list-view>
<full-view on-close="_onClose" selected-id="{{idSelected}}"></full-view>
Each element models should have a property "Selected ID", to make it possible to perform databinding. In <full-view> you must need to add a property as follows:
selectedId:{type:String, observer:"selectedIdChanged"}
So, when selectedId changes in <list-view> will also change in <full-view>
Now, you only need to add a new function in <full-view> to do something with this changed selectedId
selectedIdChanged: function(newValue, oldValue){
if(newValue!= undefined && newValue!=null){
//do something with selected Id
}
},
You could give an id for both list-view and full-view, then define & set data attribute/property for <full-view> from the _onItemClick.
<list-view id='l_view' data="[[fileData]]" on-item-click="_onItemClick"></list-view>
<full-view id="f_view" data="{}" on-close="_onClose"></full-view>
And in the script of parent.
_onItemClick: function() {
this.$.f_view.data = this.$.l_view.selected;//or any attribute of the selected item
this.$.pages.selected = 1;
},

Multiple QQuickWidgets with one QQmlEngine

I've got a problem and hope you can help me.
I have multiple QQmlWidgets where different instances of same components should be shown.
The components are created at runtime and use specific properties from it's parent widget.
The problem is, that there are multiple nested items in those components, so they are loading very slow.
I've decided to load them all to QQmlEngine at application preload stage, and after just create them when necessary.
So all my QQmlWidgets got same QQmlEngine and same root context.
To differ properties of different widgets I'm creating every instance of component in separate context (one per QQmlWidget).
After creating I'm setting parent item of newly created object to root item of QQmlWidget;
The problem is that the root item is referenced in the dynamically created objects and they could not find it.
Can you suggest any solution? I'm posting simplified version of my code below.
// main.cpp
QQmlEngine* e = new QQmlEngine;
QWidget* ww1 = new QWidget;
QWidget* ww2 = new QWidget;
QQuickWidget* w1 = new QQuickWidget(e, ww1);
QQuickWidget* w2 = new QQuickWidget(e, ww2);
w1->setSource(QUrl::fromLocalFile("main.qml"));
w2->setSource(QUrl::fromLocalFile("main.qml"));
QQmlComponent* comp = new QQmlComponent(e, "comp.qml");
QQmlContext* c1 = new QQmlContext(e);
QQmlContext* c2 = new QQmlContext(e);
QQuickItem* it1 = qobject_cast<QQuickItem*>(comp->create(c1));
it1->setParentItem(w1->rootObject());
QQuickItem* it2 = qobject_cast<QQuickItem*>(comp->create(c2));
it2->setParentItem(w2->rootObject());
ww1->show();
ww2->show();
//main.qml
Rectangle {
id: root
}
//comp.qml
Rectangle {
anchors.top : root.top
}
the error:
comp.qml - ReferenceError: root is not defined
Thanks in advance.
When a component is being loaded a parent is not set and it becomes set only after call of setParentItem method. It can be fixed by setting anchor when parent changes.
// comp.qml
Rectangle {
onParentChanged: { anchors.top = parent.top; }
}

Get all selected items in a TreeStore

I have a TreeStore that you can drill into. It's only two levels deep. When you get to the second level and you click on a leaf it takes you to a detail card.
How do I, in the detail card, show the full path?
So say I have;
- A
- 1
- 2
- B
- 1
- 3
- C
- 5
- 2
So when I click on B and then 3 I want to have "B" and "3" ideally in a Javascript variable that I can then pass to a WebService.
I believe SenchaTouch has no built in functionality for this.
You can listen for the itemtap event and then store the title of your item in an array.
When you show your detailcard you could pass this array to you webservice and show the joined array in your card.
Unfortunately i don't know what your code looks like and if you use the MVC approach but it would probaply something like this:
breadcrumbs = []
onItemTap = function( list, target, record ){
breadcrumbs.push( record.get('title') );
}
onLeafItemTap = function() {
breadcrumpsStr = breadcrumbs.join('->');
// send them to your webservice
// set in your detailCard
breadcrumps = []
}
When you provide your code I could help you more.