tiberiuzuld / angular-gridster2

Angular gridster 2
https://tiberiuzuld.github.io/angular-gridster2
MIT License
1.26k stars 380 forks source link

Drag & drop component into gridster #399

Open nathanagez opened 5 years ago

nathanagez commented 5 years ago

Hello, I'm working on a project where users will all have there own dashboard composed of multiples angular modules. Actually i'm a little bit stuck. I don't know how to make an instance of my component/how to create this component in gridster when I drop it.

Interface is composed of a sidebar containing all my angular modules (actually this is just text, but in the future, when I will drop a picked module, an event will make an instance of the selected module in gridster).

I give you a screenshot of what I want to do, it will be more explicit.

screenshot

If you have a link, a track that can unstuck me it will be great. Thank you beforehand !

CollinGraf314 commented 5 years ago

So before you go any further, take a quick look at #245. I do not believe angular-gridster2 currently supports the ability to drag items on/off of it.

That said, it is fairly easy to allow someone to click a button in a tray that adds a specific component to the next available free space in the grid. I am doing something kind of similar to what you are trying to do, and the way that I handle it is that I have a component that represents a generic item on the grid (or a widget-shell if you would), and then based on one of that component's inputs, I use the [ngSwitch] directive to choose which widget-content component to display.

If you need more guidance let me know and I can try to throw together a quick stackblitz for you to use for reference.

nathanagez commented 5 years ago

Hi @CollinGraf314 , after some research I succeeded to create dynamic components as you can see with these screenshots.

1 2 3 4

Although this is always the same component created, on the sidebar I have an object displayed with an *ngFor with different identifier that allow me to create the correct component, my problem is when I drop a thing from another component (here my menu component to my dashboard component) I want to recover the data that tell me to create the right component.

I tried with Output decorator but I don't have any instance of my menu in the dashboard component where gridster is. So I can't call my EventEmitter to recover the data.

Have you a solution ? Regards.

CollinGraf314 commented 5 years ago

Because of issue #245 the best you can do is allow for the user to drag a widget from your menu and drop it somewhere on the dashboard, then independent of where you drop it, add it to the next open spot on the grid. In order to do this run a function in the onDrop callback of whatever draggable library you are using. In that function you can save what ever information you need from the dropped object and then call a function from a service shared between your menu and dashboards components that will pass on the data to your dashboard. Then have your dashboard create the new widget and add it to your grid.

If you NEED the functionality of being able to drag/drop items from off the grid then you'll either need to use a different library or you'll need to modify the library yourself. If you were to go the second route and were able to make something stable, please make a pull request as such functionality would be a huge boon to this library and it seems that tiberiuzuld is no longer actively doing development

Konstruktour commented 5 years ago

Related #357 #254

nathanagez commented 5 years ago

I finally found a solution, I created a repository to share my work. Feel free to test it , it still in development but main ideas and functionalities are here.

https://github.com/NastyZ98/angular6-dynamic-dashboard

CollinGraf314 commented 5 years ago

Thank you @NastyZ98! I will take a look at your repository, but sadly neither Tiberiuzuld or I have much time to do development on this at the moment. Hopefully we can implement this functionality in the future, but for now the best I can offer is to review any pull requests related to this issue.

I am going to keep this issue open, because I think this is an enhancement that we want to implement.

viethien commented 5 years ago

Hello @NastyZ98 , Thanks for your sharing at https://github.com/NastyZ98/angular6-dynamic-dashboard I followed your code and add some init data in ngOnInit, but <ndc-dynamic class="no-drag" [ndcDynamicComponent]="item.component" (moduleInfo)="display($event)"> did not fire ngOnInit, how can I trigger ngOnInit? I tried ndcDynamicCreated but not success. Thanks

CollinGraf314 commented 5 years ago

@viethien, angular-gridster2 now supports dragging widgets from outside the grid and dropping them into it. Check out the demo here: https://tiberiuzuld.github.io/angular-gridster2/emptyCell. Pay attention to the enableEmptyCellDrop, enableEmptyCellDrag, and emptyCellDropCallback properties.

Robinyo commented 5 years ago

Describe the bug

I have looked at the source code for the Empty Cell demo (as well as the code in NastyZ98's Angular 6 Dynamic Dashboard repository) in order to add support for drag and drop (from a widget palette to a dashboard) to my application.

However, at runtime (after dragging and dropping a widget from the palette onto the dashboard) I receive the following error:

Screen Shot 2019-06-17 at 10 20 50

Note: The new widget is added to the dashboard (gridster).

Demo

Firebase Hosting: Serendipity

Source Code

GitHub: Serendipity

I think the issue is related to this line of code:

emptyCellDropCallback: this.onDrop,
// emptyCellDropCallback: this.onDrop.bind(this),

From my dashboard.component.ts

If I bind the emptyCellDropCallback as follows:

// emptyCellDropCallback: this.onDrop,
emptyCellDropCallback: this.onDrop.bind(this),

I do not receive the error, however, the callback is called twice (two new widgets are added to the dashboard (gridster)).

The drag source (widget palette - nav.component.html, nav.component.ts):

  <mat-sidenav position="end" mode="side">

    <mat-nav-list>

      <a *ngFor="let item of toolPaletteItems"
        mat-list-item>
        <img matListIcon
             [src]="item.icon"
             [alt]="item.name"
             class="app-nav-list-icon"
             draggable="true" (dragstart)="onDragStart($event, item.id)">
        {{item.name}}
      </a>

    </mat-nav-list>

  </mat-sidenav>

Setup

Angular 7.2.15 "angular-gridster2": "^7.2.0" "ng-dynamic-component": "^4.0.3", "highcharts": "^7.1.2" "highcharts-angular": "^2.4.0" "typescript": "^3.2.4"

See: package.json

Robinyo commented 5 years ago

Sample Dashboard with widget palette:

dashboard-widgets
Robinyo commented 5 years ago

I think the console error is actually related to the itemChangeCallback:

// itemChangeCallback: this.itemChange.bind(this),

So I commented it out, but the error still occurs occasionally ...

Still not sure about the emptyCellDropCallback:

emptyCellDropCallback: this.onDrop,
// emptyCellDropCallback: this.onDrop.bind(this),
Robinyo commented 5 years ago

Ok, my bad it seems the (intermittent) error was caused by not binding the 'this' pointer:

emptyCellDropCallback: this.onDrop.bind(this),

Cleared my browser cache and rebuilt everything and the application seems to work as expected :)

Demo

Firebase Hosting: Serendipity

viethien commented 5 years ago

@Robinyo @CollinGraf314

How can you get drop position (x,y) value when drag into dashboard? Currently, I can not get x, y in event value.

Thanks

CollinGraf314 commented 5 years ago

Check out the emptyCellDropCallback. The gridsterItem parameter should hold the x, y position of the item on the grid. https://tiberiuzuld.github.io/angular-gridster2/emptyCell

viethien commented 5 years ago

@CollinGraf314

When i put emptyCallback(event, item), emptyCellDropCallback call twice, the first one it put item is undefined, the second one i can get item position.

How can I prevent first call?

Thanks

viethien commented 5 years ago

@CollinGraf314 @NastyZ98 @Robinyo

How can i get rows and columns of gridster when I change fixHeight or fixWidth property? I tried to use gridSizeChangedCallback: this.gridSizeChanged but not success, it return rows and colums of gridster item.

gridSizeChanged(gridster){ console.log(gridster.rows + '-' + gridster.columns); }

townaquaticclub commented 4 years ago

Ok, my bad it seems the (intermittent) error was caused by not binding the 'this' pointer:

emptyCellDropCallback: this.onDrop.bind(this),

Cleared my browser cache and rebuilt everything and the application seems to work as expected :)

Demo

Firebase Hosting: Serendipity

@Robinyo : Can you give me the source code.

Robinyo commented 4 years ago

@townaquaticclub

See: https://github.com/Robinyo/serendipity

oOBlinkOo commented 3 years ago

it is posible to set rows and columns of gridsterItem before to be catch on onDrop event?

 onDragStart(event,card){
    event.dataTransfer.setData('widgetIdentifier', 'message');
    'event.something.rows:2'    <-Set rows of the preview
    'event.something.cols:2'     <-Set cols of the preview
  }

so when the preview is displayed i could see a preview with 2 or more cols and rows?

Benjarmil commented 3 years ago

@oOBlinkOo You set the defaultItemCols and defaultItemRows properties on the options object and then call options.api.optionsChanged() to re-size the preview.

onDragStart (event,card) {
  this.options.defaultItemCols = 2;
  this.options.defaultItemRows = 2;
  this.options.api.optionsChanged();
}
naganand123 commented 3 years ago

Hi,

Can please share me the demo link for below drag and drop charts. In our project we want to implement like this we are using Backbone.JS, Jquery, D3.js, HighCharts. Please help me

image

image