1

I have created a dashboard using angularjs, kendoui charts and angular gridster (https://github.com/ManifestWebDesign/angular-gridster).

So I have a function to add a gridster with chart like below :-

// add widget to a dashboard
$scope.addWidget = function () {
  
  // new widget configuration
  var newWidget = {
    id: $scope.allWidgetData.selectedOption.id,
    data_source: {},
    config: {
      name: $scope.allWidgetData.selectedOption.name,
      sizeX: 3,
      sizeY: 2,
      row: $scope.row,
      col: $scope.col
    }  
  };
}

// make api call and save data

I can save this object to backend and get the values too. I am setting row and col values for each chart as follows as the sizeX and sizeY values are constant as 3 and 2.

  1. First chart row:0 and col:0
  2. Second chart row:0 and col:3
  3. Third chart row:2 and col:0
  4. Fourth chart row:2 and col:3

I referred and searched for solution on below pages :-

  1. Save gridster layout using angularjs

  2. https://github.com/ManifestWebDesign/angular-gridster

So now my HTML is like below so I set row and col values:-

<div gridster="gridsterOptions" ng-if="isShowing(index)">
    <ul>
        <li gridster-item="widget" ng-repeat="widget in widgetData.availableOptions" row="widget.config.row" col="widget.config.col" style="overflow:hidden;" >
            <div class="box">                         

            // kendo ui chart in  div
        </li>
    </ul>       
</div> 

My gridster configuration is like below :-

$scope.gridsterOptions = {
      minRows: 2, // the minimum height of the grid, in rows
      maxRows: 100,
      columns: 6, // the width of the grid, in columns
      colWidth: 'auto', // can be an integer or 'auto'.  'auto' uses the pixel width of the element divided by 'columns'
      rowHeight: 'match', // can be an integer or 'match'.  Match uses the colWidth, giving you square widgets.
      margins: [10, 10], // the pixel distance between each widget
      defaultSizeX: 3, // the default width of a gridster item, if not specifed
      defaultSizeY: 2, // the default height of a gridster item, if not specified
      mobileBreakPoint: 600, // if the screen is not wider that this, remove the grid layout and stack the items
      swapping: false,
      pushing: true,
      floating: false,
      resizable: {
          enabled: true,
          start: function(event, uiWidget, $element) {}, // optional callback fired when resize is started,
          resize: function (event, uiWidget, $element) {
          }, // optional callback fired when item is resized,
          stop: function(event, uiWidget, $element) {
          } // optional callback fired when item is finished resizing
      },
      draggable: {
         enabled: true, // whether dragging items is supported
         handle: '.box-header', // optional selector for resize handle
         start: function(event, uiWidget, $element) {}, // optional callback fired when drag is started,
         drag: function(event, uiWidget, $element) {}, // optional callback fired when item is moved,
         stop: function(event, uiWidget, $element) {          
        } // optional callback fired when item is finished dragging
      }
  };  

When I get the gridster items from backend they are in random order and gridster does not align them as per row and col values.

1 Answer 1

2

I created a working pen for you how to do this: https://codepen.io/shnigi/pen/JLVZpK

I had a similar problem, this is how I tackled it. Make sure you are referencing to right object value. You may also have to set positions when your ajax call is ready:

<li ng-repeat="widget in widgets"
          class="panel" gridster-item
          row="widget.posY"
          col="widget.posX"
          size-x="widget.width"
          size-y="widget.height">
        <div class="panel-heading">
          <h3 class="panel-title">{{widget.title}}</h3>
        </div>
</li>

Mobile breakpoints are also issue as you set the widget position and then you may have different resolution. So what I did here is that I am now using this fork:

https://github.com/arkabide/angular-gridster

I count the columns based on resolution and have "dynamic" columns turned on.

$scope.gridsterOptions = {
  resizable: {
    enabled: false,
  },
  floating: true,
  pushing: true,
  swapping: true,
  isMobile: true,
  mobileBreakPoint: 768,
  columns: getColumns(),
  dynamicColumns: true,
  minWidthToAddANewColumn: 255,
  rowHeight: 400,
  draggable: {
    enabled: true,
    handle: '.panel-heading'
  }
};

const getColumns = () => {
  const browserWidth = $window.innerWidth;
  if (browserWidth < 1300) {
    return 3;
  } else if (browserWidth < 1500) {
    return 4;
  } else if (browserWidth < 1700) {
    return 5;
  }
  return 6;
};

There are some issues with the widget positioning if resolution changes, but this is the best solution I have got so far.

So make sure you load all data before assigning it using promises. Pseudo code like this:

const loadedWidgets = [];
    if (settings) {
      const loadAllWidgets = () => new Promise(resolve =>
          loadedWidgets.push(widget);
          resolve();
        }));

  const actions = settings.chartsettings.map(loadAllWidgets);
  Promise.all(actions).then(() => {
    const widgetList = loadedWidgets.map(widget => widget);
    $scope.widgets = widgetList;
  });
}

I guess your issue is related to object referencing or you are not setting position with promises. You can also try the fork I am using. Because for me this setup works and the widgets appear where I save them.

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

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.