Quantcast
Channel: Wijmo
Viewing all 89 articles
Browse latest View live

How to Filter Hierarchical Data in FlexGrid and Angular

$
0
0

Filtering is an important feature for large data sets and may vary depending on the structure of the data being filtered. In this post, we’ll walk through filtering hierarchical data in the FlexGrid control in an Angular application.

Get the Fiddle | Download Wijmo

FlexGrid provides support for filtering and allows you to define your own filter function as well. The most common way to do this through the ICollectionView interface, but ICollectionView was designed to handle only flat data, so to handle hierarchical data we’llneed a different approach.

The Problem

Imagine we have a hierarchical collection consisting of “state” objects that have a collection of “city” objects. This could be expressed in JavaScript as follows:

// some hierarchical data
var data = [
{
name: 'Washington', type: 'state', population: 6971, cities: [
{ name: 'Seattle', type: 'city', population: 652 },
{ name: 'Spokane', type: 'city', population: 210 }
]
}, {
name: 'Oregon', type: 'state', population: 3930, cities: [
{ name: 'Portland', type: 'city', population: 609 },
{ name: 'Eugene', type: 'city', population: 159 }
]
}, {
name: 'California', type: 'state', population: 38330, cities: [
{ name: 'Los Angeles', type: 'city', population: 3884 },
{ name: 'San Diego', type: 'city', population: 1356 },
{ name: 'San Francisco', type: 'city', population: 837 }
]
}
];

If you assigned this collection to a FlexGrid’s itemsSource property, the grid would automatically display the states, but not the cities.

If you then assigned the value “cities” to the grid’s childItemsPath property, the grid would show the states and then would add child items for each element in the “cities” array. Note that in this case we have only two levels, but this process could continue to any depth.

So far, so good. But the topic of discussion here is filtering this hierarchical data.

By default, the ICollectionView used internally by the FlexGrid only deals with flat data. So you could use it to filter the states only. But what if you wanted to filter by state AND city?

The Solution: Define Rules for the Filter

To do this, we start by defining a few rules for the filter:

  1. The filter will be applied to the “name” property only.
  2. If a state (top level item) satisfies the filter, all its cities will be displayed
  3. If a city (second level item) satisfies the filter, its parent state will be displayed.

Rule #1 is arbitrary. We could use more properties in the filter.

Rule #2 is also arbitrary. If you think showing states without their cities would be useful to users, the rule can be removed.

Rule #3 is the most important one. If a user searched for “Spokane”, the grid should display the city and also its parent state. Failing to do so would create a grid with orphan items.

We’ll apply these rules directly to the grid, by traversing all rows and setting their visible property to true only if they pass the filter. The code looks like this:

// update row visibility
function updateRowVisibility(flex, filter) {
var rows = flex.rows,
filter = filter.toLowerCase();
for (var i = 0; i < rows.length; i++) {
var row = rows,
state = row.dataItem,
rng = row.getCellRange();
// handle states (level 0)
if (row.level == 0) {
// check if the state name matches the filter
var stateVisible = state.name.toLowerCase().indexOf(filter) >= 0;
if (stateVisible) {
// it does, so show the state and all its cities
for (var j = rng.topRow; j <= rng.bottomRow; j++) {
rows[j].visible = true;
}
} else {
// it does not, so check the cities
for (var j = rng.topRow + 1; j <= rng.bottomRow; j++) {
var city = rows[j].dataItem,
cityVisible = city.name.toLowerCase().indexOf(filter) >= 0;
rows[j].visible = cityVisible;
stateVisible |= cityVisible;
}
// if at least one city is visible, the state is visible
rows.visible = stateVisible;
}
// move on to the next group
i = rng.bottomRow;
}
}
}

The code uses the GroupRow’s getCellRange method to retrieve an object that contains the group’s top and bottom rows, then uses those limits to loop through entire states or individual cities.

Implementing the Solution in Angular

Let’s get started.

  1. Create an index.html file.
  2. Add the references to the controls.
  3. Add the Angular Interop.js files.
  4. Add a layout for the template. You can copy and paste the code below:
<html>
<head>
<!-- Stylesheet -->
<link rel="stylesheet" type="text/css" href="http://cdn.wijmo.com/5.latest/styles/wijmo.min.css" />
<!-- Wijmo References -->
<script src="http://cdn.wijmo.com/5.latest/controls/wijmo.min.js"></script>
<script src="http://cdn.wijmo.com/5.latest/controls/wijmo.grid.min.js"></script>
<!-- Wijmo Angular Interop -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script src="http://cdn.wijmo.com/5.latest/interop/angular/wijmo.angular.min.js"></script>
<!-- Angular module -->
<script src="app.js" type="text/javascript"></script>
</head>
<body>
<div ng-app="app" ng-controller="appCtrl">
<wj-flex-grid
control="flex"
style="height:260px;width:320px"
items-source="data"
headers-visibility="Column">
</wj-flex-grid>
</div>
</body>
</html>

Since we’re building an Angular application, we need to create our Angular Module and Controller.

Create a new file called app.js and copy and paste the code below.  Note: the index.html markup already includes a script tag to reference this file. Be sure the file is in the right location on your machine.

'use strict';
// define app, include Wijmo 5 directives
var app = angular.module('app', ['wj']);
// controller
app.controller('appCtrl', function ($scope) {
});

We can now add our small data set to the controller:

 // some hierarchical data
var data = [
{
name: 'Washington', type: 'state', population: 6971, cities: [
{ name: 'Seattle', type: 'city', population: 652 },
{ name: 'Spokane', type: 'city', population: 210 }
]
},
{
name: 'Oregon', type: 'state', population: 3930, cities: [
{ name: 'Portland', type: 'city', population: 609 },
{ name: 'Eugene', type: 'city', population: 159 }
]
},
{
name: 'California', type: 'state', population: 38330, cities: [
{ name: 'Los Angeles', type: 'city', population: 3884 },
{ name: 'San Diego', type: 'city', population: 1356 },
{ name: 'San Francisco', type: 'city', population: 837 }
]
}
];
$scope.data = new wijmo.collections.CollectionView(data);

On the last line of code, we set the $scope.data object to a CollectionView object, passing the data variable as a parameter. As previously mentioned, the ICollectionView interface represents our data as a flat structure, like an array or list of Objects. If you open the index.html file in a browser, you’ll only see the states of each item in the CollectionView.

CollectionView flat structure

CollectionView flat structure

In order to display the cities, we need to assign the childItemsPath property of the FlexGrid to “cities.” In your index.html file, add the childItemsPath attribute to the wj-flex-grid element and set the attribute to cities like below:

<wj-flex-grid
control="flex"
style="height:260px;width:320px"
items-source="data"
child-items-path="cities"
headers-visibility="Column">
</wj-flex-grid>

If you save the file and refresh the browser, you’ll see the city rows under each state. This is called a Tree View.

Filtering in a TreeView

Filtering in a TreeView

With the Tree View enabled, it’s now time to add the filter! If we use the CollectionView filter, only the parent item’s data properties will be considered when filtering or sorting. Instead we’ll create our own filter function. We’ve already defined our filter function above, but there are a few more steps to finalize our application.

  1. In the index.html file, add an input element and the ng-model directive to allow Angular to detect changes in the input element:
     <p>
    <input ng-model="filter" />
    </p>
    
  2. In the app.js file, add a $watch function to listen for changes in the filter model.
    // update row visibility when filter changes
    $scope.$watch('filter', function() {
    updateRowVisibility();
    });
    
  3. Finally, add the function that filters! We’ll handle filtering by simply hiding the rows that don’t match the filter. So as the user is typing, the grid will automatically update based on our filter function. Copy the updateRowVisibility function from above to the Angular controller.

Now that you’ve successfully implemented Hierarchical filtering, try using a more complicated data set or modifying the rules/behavior of your filter function.

Check out full implementation here:http://jsfiddle.net/troy_taylor/etx8em7w/

The post How to Filter Hierarchical Data in FlexGrid and Angular appeared first on Wijmo.


Video: Creating an Angular 2 Application with Wijmo Controls Session at Echo 2016

$
0
0

GrapeCity has been developing JavaScript products for over six years, and in summer of 2016, hosted two global conferences on JavaScript in Seoul and Tokyo. Chris Bannon, Wijmo product manager, and Alex Ivanenko, program manager, presented two talks to their audiences. This recording is from Alex’s presentation in Tokyo.

Abstract

Go over key aspects of creating an Angular 2 SPA application, and learn how to use GrapeCity Wijmo 5 controls there, and what are the benefits that Wijmo 5 brings. Find out some technical details of Wijmo 5 for Angular 2 interop implementation.

Alex Ivanenko, Program Manager of Wijmo, at Echo Seoul

Alex Ivanenko, Program Manager of Wijmo, presents at Echo 2016

Video

This talk was simultaneously translated so the speaking is at a slower pace.

Slides

The post Video: Creating an Angular 2 Application with Wijmo Controls Session at Echo 2016 appeared first on Wijmo.

Wijmo Build 5.20162.207 Available

$
0
0

We’ve just released Build 207 and it includes some huge interop improvements, nice new features, some new samples and, of course, bug fixes.

Angular 2 Support for RC6

Angular 2 RC6
Wijmo has been upgraded to support Angular 2 RC6. It’s been challenging, but we’ve been able to keep pace with the Angular team during their prerelease phase. We’ll continue to do so and plan on releasing support when Angular 2 officially releases. Learn more about our Angular 2 support

ReactJS Support

ReactJS and Wijmo
Wijmo is dedicated to interop in any framework. This release contains official support for ReactJS, and you can use Wijmo controls in any ReactJS application as React components.

React Samples

VueJS Support

vuejs and wijmo
VueJS is another framework gaining traction. Many customers have requested VueJS support in Wijmo. This release offers official support of VueJS, and you can use Wijmo controls in any VueJS application as Vue components. Note: VueJS 2.0 support will be coming soon as well.

VueJS Samples

FlexGrid Footers

flexgrid footers
We’ve added support for column footers in FlexGrid. Easily add custom footers to columns using the new columnFooter in FlexGrid. Take a look at this new feature in the FlexGrid Custom Footers sample.

New Charting Capabilities

flexradar chart
This release includes a new FlexRadar chart control that can be used to create radar-type charts. Take a look at the new FlexRadar Intro sample.

funnel chart type
We also added a funnel chart type to FlexChart. Take a look at the new funnel chart type in the FlexChart Intro sample.

New Help System

new docs
Last, but not least, we’ve completely rebuilt and redesigned our online documentation. The redesign includes better content, layout, navigation, search and much more. Take a look at our new online documentation.

Change Log

  • Angular 2: Wijmo interop adapted to RC.6, and can still work with RC.5. Angular 2 Info
  • Angular 2: all samples ported to RC.6 Angular 2 Explorer
  • Angular 2: added support for NgModule system introduced in RC.5. Each Wijmo Ng2 module includes corresponding NgModule that represents the module in Ng2 application and exports all its components. NgModule’s name is inferred from ES6 module name, e.g. for ES6 module wijmo/wijmo.angular2.grid.filter the name of corresponding NgModule is WjGridFilterModule. Only few samples are reworked so far to use NgModel: InputIntro, FlexGridIntro, ngForms and FlexSheetExplorer. The latter is SPA application that implements lazy modules loading.
  • ReactJS: Added a new interop module for React: wijmo.react.js. ReactJS Interop sample | How to Use Wijmo in ReactJS Apps blog
  • VueJS: Added a new interop module for Vue: wijmo.vue.js. VueJS Interop sample | How to Create Great VueJS applications Using Wijmo Controls blog
  • Completely redesigned help system. new Wijmo 5 Documentation
  • Added support for column footers panel on the FlexGrid. Column footers have their own ‘columnFooters’ grid panel (similar to columnHeaders and rowHeaders). To add column footers to a grid, add one or more rows to its columnFooters panel. For example: grid.columnFooters.rows.push(new wijmo.grid.GroupRow()) In this example, we added a GroupRow, which will cause the grid to automatically display the aggregates set in each Column. Alternatively, you could add on or more regular rows, and set the cell contents of those row using the columnFooters.setCellData method: grid.columnFooters.rows.push(new wijmo.grid.Row()); grid.columnFooters.setCellData(0, 0, ‘column footer value’); FlexGrid Custom Footers sample
  • Added a new charting control: FlexRadar for creating radar and polar charts. The control is in new module: wijmo.chart.radar.js. FlexRadarIntro samples (PureJs, Angular 1/2) are added to demonstrate the new control’s features. FlexRadar Intro sample
  • Added a new funnel chart type. Added funnel chart sample to FlexChartIntro sample. FlexChart Intro sample
  • Added a new FlexGrid.newRowAtTop property to control whether the new row template should be displayed at the top or at the bottom of the data rows.
  • Improved FlexGrid scrolling with frozen cells (used to be a little jerky in IE).
  • Angular 2: added the autoSizeRows boolean property to the wjFlexGridCellTemplate directive that allows to disable automatic row height expansion.
  • Angular 1/2: added support for cell templates for FlexGrid column footers. WjFlexGridCellTemplate.cellType property now accepts ‘ColumnFooter’ and ‘BottomLeft’ to be applied to the corresponding cell types. In order to get a cell value in ‘ColumnFooter’ cell templates the $value (Angular 1) or cell.value (Angular 2) properties can be used.
  • Improved performance of Row/Col.IsSelected method.
  • Improved performance of FlexGrid.preserveOutlineState property.
  • Improved keyboard support in wijmo.Menu. Now users can use the keyboard to open the menu with (Enter/f4/alt+up/alt+down) and to navigate the options (up/down/ autosearch).
  • Added a Gauge.showTicks property that causes linear and radial gauges to show tick marks on the gauge face. The tick marks start from “min” to “max” at every “step”. By default, the tick marks are white and 2 pixels in thickness. They can be styled using a “.wj-gauge .wj-ticks” CSS selector to customize their “stroke” and “stroke-width” values.
  • Added an optional ‘dataItem’ parameter to the DataMap.getDisplayValues method. The dataItem can be used to restrict the list of display values based on properties of the data item being rendered/edited (see http://wijmo.com/topic/flexgrid-datamap-that-is-row-dependent/).
  • Added support for “deep-binding” to the ListBox control (e.g. “customer.name”).

New Samples

Get Started

Download
Wijmo build 5.20162.207

The post Wijmo Build 5.20162.207 Available appeared first on Wijmo.

Video: Inside Wijmo 5 Session at Echo 2016

$
0
0

GrapeCity has been developing JavaScript products for over six years, and in summer of 2016, hosted two global conferences on JavaScript in Seoul and Tokyo. Chris Bannon, Wijmo product manager, and Alex Ivanenko, program manager, presented two talks to their audiences. This recording is from Chris’s presentation in Tokyo.

Abstract

The browser landscape has changed greatly since we started and we have learned a lot along the way. Today, we manage Wijmo 5, a suite of JavaScript UI controls, specializing in a high-performance datagrid and powerful charts. In this session, we will give you a look inside our project. We will go over the collections of tools, frameworks, languages and patterns that we have refined over the years. You walk away from this session with useful tips for managing large-scale JavaScript applications.

Chris Bannon, Product Manager of Wijmo, at Echo Seoul

Chris Bannon, Product Manager of Wijmo, presents at Echo Seoul

Video

This talk was simultaneously translated so the speaking is at a slower pace.

Slides

The post Video: Inside Wijmo 5 Session at Echo 2016 appeared first on Wijmo.

Angular 2 Officially Released and Wijmo Supports It

$
0
0

“Congratulations to the Angular Team on officially releasing Angular 2!”

With love (and a huge sigh of relief),
Team Wijmo

angular 2 released

We couldn’t be happier to see Angular 2 officially release! It’s been a great challenge to keep pace with the NG2 team, and our efforts have paid off: Wijmo has offered deep integration for Angular 2 since the early alpha versions.

Just hours after Angular 2’s release, Wijmo provided a nightly build that supports Angular 2‘s official version! Our Angular support offers rich declarative markup for all of our components, including our famous FlexGrid. Read more about what we think makes the best Angular 2 Data Grid.

Angular 2 is ready for products and Wijmo components are, too! We already have customers building productions applications with both, and we look forward to seeing what you build with them too.

Read more about the official Angular 2 release and Wijmo’s Angular 2 support.

The post Angular 2 Officially Released and Wijmo Supports It appeared first on Wijmo.

Wijmo Build 5.20162.211 Available

$
0
0

We’ve just released Build 211 and it includes some huge interop features.

Angular 2 Officially Releases

angular 2 released
We couldn’t be happier to see Angular 2 officially release! It’s been a great challenge to keep pace with the NG2 team, and our efforts have paid off: Wijmo has offered deep integration for Angular 2 since the early alpha versions.

Just hours after Angular 2’s release, Wijmo provided a nightly build that supports Angular 2‘s official version! Our Angular support offers rich declarative markup for all of our components, including our famous FlexGrid. Read more about what we think makes the best Angular 2 Data Grid.

This release includes official support for Angular 2.0.0.

Change Log

New Samples

Get Started

Download Wijmo build 5.20162.211

The post Wijmo Build 5.20162.211 Available appeared first on Wijmo.

Happy Birthday, Wijmo 5!

$
0
0

It’s hard to believe Wijmo is another year old! Wijmo is six years old, and Wijmo 5 is officially two years old. Last year I wrote up a five year history of Wijmo, so this year, let’s look at Wijmo 5.

It’s been a great year for Wijmo as our product line has matured. We’ve seen wide adoption among some incredible enterprises like Microsoft, Apple, Tesla, Thomson Reuters and ESRI. These companies are utilizing Wijmo 5 and saving countless hours of time. It’s been great to work with them and adapt Wijmo to their needs.

Enter our Wijmo Birthday giveaway!

While the first year of Wijmo 5 was about building a core set of controls and collecting customer feedback, the second year of Wijmo 5 was about expanding our controls based on customer needs. Let’s look at how Wijmo has grown.

happy-birthday-wijmo

Wijmo’s Interop Support

Wijmo 5 has zero dependencies and can be used on its own. At the same time, we know that many of our customers will choose a framework in which to build their applications, so we decided from the beginning to build interop libraries in Wijmo that offer deep integration with popular frameworks. Wijmo 5 first shipped with Angular 1.x and KnockoutJS support, and the Angular 1 interop has been wildly popular with our customers. The great thing about our interop libraries is that you’re using the same components across any framework (or none). In fact, we have customers that are now migrating their Angular 1 applications to Angular 2 while using our same controls.

This year, we decided to fully commit to Angular 2 support as well. Our team has done an incredible job of keeping up with the Angular 2 team, and we shipped support for Angular 2 just hours after it officially released. We also think that we have the best data grid for Angular 2 in the industry.

Another popular framework in ReactJS. We recently released full support for ReactJS in Wijmo and created quite a few samples using the two together. While Angular has been a favorite here, ReactJS is definitely appealing in its own way.

Lastly, we’ve had requests for supporting a brand-new framework called VueJS. Naturally, we released support for VueJS (1 and 2) so that our same controls can be used in nearly any JS framework.

Wijmo’s Flex Philosophy: Extensions

Another key aspect to Wijmo 5 is our “flex philosophy.” We build small core controls and make them very extensible. We then use the extensibility model to build custom (and optional) features. By limiting the feature set in the core controls, we can keep them lean and fast. At the same time, creating optional extensions gives our customers the features they need. Throughout the last year, we’ve created many extensions for the FlexGrid and FlexChart, all based on customer requests.

Here are some of the extensions we have recently released:

  • FlexGrid Filter – an Excel-like filter dropdown for every column that supports conditional of value-based filtering
  • FlexGrid GroupPanel – a drag-and-drop grouping feature for FlexGrid that allows end users to customize the grid
  • FlexGrid RowDetails – a template row in the grid that allows you to put extra details in any row
  • FlexChart Analytics – a set of tools for adding analytical graphics to charts like trendlines and indicators
  • FlexChart RangeSelector – a dynamic slider for changing the date rang displayed in a timeline chart
Add expandable and collapsible detail rows with RowDetail

Add expandable and collapsible detail rows with RowDetail

Specialty Controls

Finally, as a sign that Wijmo is really maturing, we have been able to create new specialty controls that leverage our core controls.

Most recently, we released MultiRow, a version of FlexGrid that supports complex cell-wrapping within rows. This popular UI pattern in Japan has been made popular by Excel, and with our large customer base in Japan, we were happy to develop MultiRow based on their requests.

Wrap columns to prevent scrolling with MultiRow

Wrap columns to prevent scrolling with MultiRow

We’ve also released a very complete set of OLAP controls, including a PivotPanel, PivotGrid and PivotChart. This is something that is normally limited to server-side environments, but we have created for client-side applications. Our OLAP controls leverage the power of modern browser engines to create analytical grids and charts based on massive data sets. We also have plans to release server-side support for scenarios where you might still want it.

Beyond that, we have released FlexSheet, a spreadsheet control and FinancialChart, a full-featured stock market chart. Creating these controls really pushes the boundaries of what our core controls are capable of.

What’s Next?

As you can see, it’s been a very productive year for  Wijmo. So what do we have planned for the future?

  • We’re going to continue to have a customer-driven roadmap. We’ll keep listening to you and developing tools that you need.
  • We will continue to polish and extend  Wijmo  as well as offer interop support for new frameworks as they emerge. In fact, we have immediate plans to release module support for Wijmo so you can use our controls in your module loader of choice. We’ll support true module loading and are planning on integrating with NPM.
  • We also plan to develop more specialty controls for reporting and data visualization as well.

Thanks for being a part of  Wijmo’s  history. It’s been another great year of building developer tools.

Enter our Wijmo Birthday giveaway: grand prize is one ticket to 2017 Fluent!

The post Happy Birthday, Wijmo 5! appeared first on Wijmo.

Integrating Wijmo Controls with Module Loaders and Bundlers

$
0
0

We’ve recently received a barrage of questions regarding Wijmo integration with various module loaders and bundlers (like SystemJS, WebPack, Angular CLI, etc), which is possible, but requires a number of extra steps. We also received a question about Wijmo npm installation, which is tightly coupled with the former.

I’d like to share with you the status of our effort destined to eliminate this complexity.

You may check the things that I’ll describe below right now using the following (or more recent) prerelease build:

http://prerelease.componentone.com/wijmo5/Nightly_C1Wijmo_5.20162.222_2016.10.10.zip

External modules

The main trouble with settling Wijmo to the aforementioned tools is that the library core (non-Ng2) modules are not "external.” Rather, they’re "global" modules accessible via the global "wijmo" variable. Loaders/bundlers work smoothly only with true (“external”) modules by following the TS/ES6 “import” statements chain in order to load or collect all necessary modules, and require a special setup for global modules.

Because of this, we created true (“external”) versions of Wijmo core library modules that should be consumed using ES6/TS ‘import’ statement. For example, the following code that used Wijmo global module:

@ViewChild('flex1') flex1: wijmo.grid.FlexGrid;
let gr = new wijmo.grid.GroupRow();

looks like here with external modules:
import * as wjcGrid from 'wijmo/wijmo.grid';
@ViewChild('flex1') flex1: wjcGrid.FlexGrid;
let gr = new wjcGrid.GroupRow();

Being true modules, they can be placed to the node_modules/wijmo folder and consumed by various loaders/bundlers in a natural way, with minimal tunings, or without tuning at all.

Npm images

The Wijmo download zip now includes the NpmImages folder with wijmo-amd, wijmo-commonjs and wijmo-system subfolders containing Wijmo external modules in different module formats (AMD, CommonJS and System respectively).

An important point here: each of these subfolder is effectively an npm image that can be installed by a command like this:

npm install <some_path>/NpmImages/wijmo-amd

The command above will install Wijmo AMD modules in the node_modules/wijmo folder of the directory from which the command was issued.

Usage examples

All Wijmo Angular 2 samples are reworked to use these new modules, and have the following record in their package.json files:

"dependencies": {
   "wijmo": "../../../../../NpmImages/wijmo-amd",
    … another modules (Ng2 etc)
}

So, it’s just enough to run “npm install” in the project folder to install both Ng2 and Wijmo libraries. The only Wijmo file which is added to projects manually is wijmo.css, which is reasonable. The only downside: if you move a sample to another location, you have to update a path to wijmo npm image in package.json.

In addition, we plan to publish .tgz files with npm images on our site and reference them in the samples using this remote location. You may find this approach in the following prerelease build: http://prerelease.componentone.com/wijmo5/C1Wijmo-Enterprise-Eval_5.20162.222.zip

With this approach, projects can be freely moved to other locations without breaking the references to Wijmo npm image. Right now this is only available for evaluation versions. We’re considering whether we can apply such an approach to licensed versions, too.

WebPack

Here’s the Angular 2 CellTemplateIntro sample adapted for usage with WebPack: http://publicfiles.componentone.com/Wijmo%205%20Files/Angular2/CellTemplateIntro_Ng2_WP.zip

The only Wijmo-specific setting here is the

import '../styles/vendor/wijmo.min.css';

statement in the src/vendor.ts file that includes wijmo.css to a bundle.

You need to perform the following steps to build and run it.

Step 1: Unzip.

It has two root folders: CellTemplateIntro, which contains the sample itself, and wijmo_zip_image, which emulates Wijmo dowload zip image, but contains only the stuff necessary for this demonstration (namely wijmo-amd npm image).

Note that the sample doesn’t contain any Wijmo library file—neither .js nor .d.ts. The only exception is wijmo.min.css in the styles\vendor folder. Because .css always requires a special treatment, this is not a wijmo-specific issue.

Step 2: Run NodeJS command prompt.

Step 3: cd to the CellTemplateIntro\CellTemplateIntro folder.

Step 4: Run "npm install"

This installs all the necessary libraries to node_modules, including the wijmo folder retrieved from the aforementioned wijmo_zip_image\NpmImages\wijmo-amd folder. The folder contains all wijmo library modules, both Ng2 interop and core (both wijmo.angular2.grid and wijmo.grid). And for each module it contains both .min.js and .d.ts files.

Step 5: Run "npm run build"

This runs the WebPack that creates an app bundle in the dist folder.

Step 6: Open wpbundle.html page in a browser.

This file loads the bundle created on the previous step and should be hosted in some web server. If you use Visual Studio, then the simplest way to run it is to open the sample solution, set wpbundle.html as a default page, and run the project.

Angular CLI

Some remarks about Angular CLI: Wijmo can be integrated there in the same simple way as to WebPack as explained above. But the trouble here is that Wijmo-minified files has a min.js extension, while module names don’t naturally include “min” in their names.

In all the loader/bundler tools, this problem—that of mapping module names to files with “min.js” extension—can be resolved by means of trivial settings, but we didn’t find any way to achieve this in Angular CLI.

At the same time, we think (OK, still think!) that adding the “min” suffix to minified file names is the right way to go, so we suppose that this is a temporary limitation that will be resolved in Angular CLI in the near future. For the time being, you need to rename “.min.js” to just “.js” before installing them to your project.

True NPM Registry

Right now, we don’t provide a possibility to perform “npm install” using “wijmo” npm registry because we have the following problem: We have two types of Wijmo builds: evaluation (with Wijmo <version> popup (nag screen) and without sources), and licensed (without popup and with sources). Each have two have two different npm registry names, but both must be installed in the same node_modules/wijmo folder. Otherwise, module names like “wijmo/wijmo.grid” used with one build will be broken when you switch to the other. We have no an immediate solution for this issue.

The post Integrating Wijmo Controls with Module Loaders and Bundlers appeared first on Wijmo.


VueJS 2.0 Released, and Wijmo Supports It!

$
0
0

VueJS announced recently that Vue.js 2.0 has been officially released, and we’re pleased to say that Wijmo supports it! Our framework-agnostic controls mean you canmigrate across frameworks seamlessly, with the same fundamental controls.

vuejs-logo

Here’s a full list of our Vue samples:

And don’t miss our blog, How to Create Great VueJS applications Using Wijmo Controls.

 

Happy coding!

The post VueJS 2.0 Released, and Wijmo Supports It! appeared first on Wijmo.

Video: Learn about ReactJS and Wijmo

Data Validation in a JavaScript Data Grid

$
0
0

Data validation is an important task for any applications that accept user input. In build 212, we added data validation to the CollectionView class, which can be used by all Wijmo controls that support data collections, including the FlexGrid.

View the Data Validation sample

HTML5 has good support for forms validation. Wijmo leverages that support and extends it with custom pseudo-classes and validation directives. For details on Wijmo form validation, please see the following articles:

How to Implement Data Validation in FlexGrid

To add validation support to a CollectionView, set the new getError property to a callback function that takes a data item and a property name as parameters, and returns a string with an error description (or null if there are no errors).

For example:

var view = new wijmo.collections.CollectionView(data, {
 getError: function (item, property) {
  switch (property) {
   case 'country':
    return countries.indexOf(item.country) < 0
     ? 'Invalid Country'
     : null;
   case 'downloads':
   case 'sales':
   case 'expenses':
    return item[property] < 0
     ? 'Cannot be negative!'
     : null;
   case 'active':
    return item.active && item.country.match(/US|UK/)
     ? 'Active items not allowed in the US or UK!'
     : null;
  }
  return null; // no errors detected
 }
});

Once you define the getError callback on a CollectionView, any control bound to the collection may use it to validate items being loaded or edited.

For example, the FlexGrid will use the validation logic in the data source to:

  • Automatically highlight errors by adding the ‘wj-state-invalid’ pseudo-class to row headers and to any cells that contain errors, and
  • Prevent users from entering invalid data into cells when editing.

The image below shows a FlexGrid bound to some data that contains validation errors:

Data validation in FlexGrid

Data validation in FlexGrid

The appearance of the cells that contains errors is defined in CSS and is easily customizable.

Validation is also applied while editing the grid. If a user tried to enter an invalid country, for example, the grid would apply the error style to the cell and would keep it in edit mode until the user selected a valid country or pressed the Escape key to cancel the edits.

This default behavior can be disabled by setting the grid’s validateEdits property to false.

This simple mechanism makes it easy to identify and prevent errors in the grid data and provides a consistent look and feel for grid validation.

View the Data Validation sample

The post Data Validation in a JavaScript Data Grid appeared first on Wijmo.

How to Create a Dynamic Dashboard in React

$
0
0

A while ago one of our customers asked for a sample showing how to create a “dynamic dashboard”—one like those you can create in the Google Analytics app. The image below shows an example:

01_dynamicdashboard

The key features of interest to the customer were:

  • There is a catalog of pre-defined configurable tile types.
  • Tiles may contain arbitrary UI elements such as rich text, charts, grids and gauges.
  • Users can create custom dashboards by adding, removing, reordering, and configuring “segments” (aka “tiles”).
  • Mobile device users can drag tiles using touch.

View the sample

We thought many customers might be interested in a sample like this, so we created a Dynamic Dashboard sample and made that available to our users. Since then, we received a significant amount of feedback, including interest in the drag-drop implementation, touch support, and component design.

The original sample was implemented using Wijmo and Angular 1.x. When we released our Wijmo React interop a few weeks ago, we thought this would be a great React sample as well, and decided to create a React-based version of the sample.

The React version of the sample looks exactly like the original, but the implementation is quite different and illustrates some interesting aspects of React development.

React Implementation and TSX files

The React version of the Dynamic Dashboard application is a TypeScript application. It uses TSX files which are the TypeScript equivalent of React JSX files.

Each TSX file typically contains one React component. Adding TSX files to Visual Studio projects is trivial. Right-click the project node in the Solution Explorer, select “Add” and then “TypeScript JSX File”. You can then write regular TypeScript code with the usual DOM-like extensions typical of React code.

The tooling provided by Visual Studio for React and TypeScript is excellent. You don’t have to waste any time worrying about configuration and can get right into coding, at which point you will get all the design-time error checking and productivity tools you are used to.

The screen below shows the project with the TSX files and the options offered by Visual Studio to fine-tune the handing of TSX files should you want to do so:

02_tsx

Application Architecture

The Dynamic Dashboard app has two types of components: the dashboard frame and the tiles in it.

The dashboard frame is a stateful component. It defines a catalog of tile types available and a list of the tiles that make up the current dashboard. It also provides logic for adding, removing, and reordering the tiles.

The tiles have no state (in the React sense). They receive data from the frame via properties (passed in as element attributes). Tiles are quite simple; the app defines nine type of tiles, including various charts, gauges, bullet graphs, and a grid.

In a traditional OOP application, all tiles would extend a base tile class. In React (and many other JavaScript frameworks), you are encouraged to use composition instead of inheritance. I see this as a limitation. Composition and inheritance are different mechanisms, each has its uses, and one does not fully replace the other.

In our app, we followed the React team’s advice and implemented our tiles using composition rather than inheritance. We define a Tile component that provides the tile border (with a header and buttons). The Tile component has a “content” property that defines the actual tile content.

Dashboard Frame Component

The “App” component implements our dashboard frame. It is instantiated with the following standard snippet of HTML in application’s “default.htm” file:

<body&rt;
  <div id="app"&rt;</div&rt;
  <script&rt;
    ReactDOM.render(React.createElement(App), document.getElementById('app'));
  </script&rt;
</body&rt;

The App parameter in the call to React.createElement is our dashboard frame component. It is implemented as follows:

var App = React.createClass({
  // define the component’s initial state
  getInitialState: function () {
    // tile names and types
    var tileCatalog = [
      { name: 'Grid', tile: Grid },
      { name: 'Radial Gauge', tile: RadialGauge },
      { name: 'Linear Gauge', tile: LinearGauge },
     …
    ];
    // tiles currently in use
    var tiles = [],
         key = 0;
    for (var i = 0; i < 4; i++) {
      tiles.push({ name: tileCatalog.name, key: key++ });
    }
    // generate some data to show in the tiles
    var data = …;
    // this is our app state
    return {
      tileCatalog: new wijmo.collections.CollectionView(tileCatalog),
      tiles: tiles,
      key: key,
      data: new wijmo.collections.CollectionView(data)
    }
  },

The App component’s state has four elements:

  • tileCatalog: list of tile types that are available and can be added to the dashboard.
  • tiles: list of the tiles currently on the dashboard.
  • key: identifier to use when creating the next tile (more on this later)
  • data: data to be shown on the dashboard (passed as a prop to all tiles)

Let’s move on to the component’s render method to see how the state is used to generate the dashboard.

We start by rendering a header with the application title and a logo. Notice how the TSX syntax looks a lot like HTML, with some minor differences. Instead of “class”, for example, we must use “className”. That is because although it looks like HTML, this is really JavaScript code, and the DOM element’s property is called “className”, not “class”, The same applies to the “for” attribute of label elements, which in TSX must be specified as “htmlFor”.

// render the dashboard
render: function () {
  var data = this.state.data;
  return <div>
    <div className="header">
      <div className="container">
        <img src="resources/wijmo5.png" alt="Wijmo 5" />
        <h1>
          Dynamic Dashboard (React)
        </h1>
      </div>
    </div>

Next, we render a section that contains a drop-down where the user can select the type of tile he wants and a button to add the tile to the dashboard.

We use a Wijmo ComboBox to show the tile catalog and to keep track of the tile type currently selected. The itemsSource and displayMameberPath properties are used to populate the list and to determine which property of the items should be displayed on the list. The current tile type is exposed by the catalog’s currentItem property. Next to the combo, there is a button that invoked the “addTile” method on the component:

    <div className="container">
      <div className="container row">
        <label>
          Select a tile type: {' '}
          <Wj.ComboBox
            itemsSource={ this.state.tileCatalog }
            displayMemberPath="name" />
          {' '}
          <button
            className="btn btn-primary"
            onClick={ this.addTile }>
            Add Tile to Dashboard
          </button>
        </label>
      </div>

The “addTile” method is implemented as follows:

addTile: function () {
  var tiles = this.state.tiles.slice(),
      key = this.state.key + 1;
  tiles.push({ name: this.state.tileCatalog.currentItem.name, key: key });
  this.setState({ tiles: tiles, key: key });
},

The method starts by making a copy of the current tiles array and incrementing the key used to uniquely identify tile instances. It adds a new item to the tiles array with the name specified by the catalog’s currentItem, and calls setState to update the state with the new tiles array.

The call to setState causes React to update the UI showing the updated tiles array.

The code that renders the dashboard tiles is typical React. Is uses the array.map method to generate a list of components that make up the UI. In this case, the components are instances of Tile following properties:

  • header: name of the tile (displayed in the tile header).
  • content: component that represents the tile content (e.g. a chart or gauge).
  • remove: a callback invoked when the user clicks the “delete” button on the tile header.
  • index: index of the tile within the tile array.
  • key: item identifier used by React to optimize rendering.

Note that the key and index parameters are used for different purposes. The index parameter is used by the App component to identify tiles in the tiles array, specifically when deleting tiles. The index of a tile may change if tiles are removed or reordered. The key parameter, on the other hand, is used by the React framework to establish a mapping between array elements and components. The key does not change when tiles are removed or reordered.

      <div className="dashboard">
        {
          this.state.tiles.map((item, index) => {
            return <Tile
              header={item.name}
              content={this.getTileContent(item.name)}
              remove={this.removeTile}
              index={index}
              key={item.key} />;
          })
        }
      </div>
    </div>
  </div>;
}

The getTileContent method creates and returns a component of a given type. It looks up the component type based on the name and calls React.createElement to instantiate the tile:

getTileContent(name: string) {
  var arr = this.state.tileCatalog.items;
  for (var i = 0; i < arr.length; i++) {
    if (arr.name == name) {
      return React.createElement(arr.tile, { data: this.state.data })
    }
  }
  throw '*** tile not found: ' + name;
},

The removeTile method acts as an event handler. It is called by the Tile component when the user clicks the delete button on the tile header. The code uses the array.filter method to select all tiles except the one that was clicked, and calls setState to update the state with the new tiles array.

As before, the call to setState causes React to update the UI showing the updated tiles array.

removeTile: function (tileIndex) {
  var tiles = this.state.tiles.filter((item, index) => {
    return index != tileIndex;
  });
  this.setState({ tiles: tiles });
},

Tile Components

The Tile component represents a frame to hold tile content (of all types). It is a simple stateless component implemented as follows:

var Tile = React.createClass({
  remove: function () {
    this.props.remove(this.props.index)
  },
  render: function () {
    return <div className="tile" draggable="true">
      <div style={{ borderBottom: '1px solid #e0e0e0', … }}>
        <div style={{ flexGrow:1, color: '#005c9c', fontWeight: 'bold' }}>
          { this.props.header }
        </div>
        <div className="buttons">
          <span className="glyphicon glyphicon-pencil"></span>
          <span className="glyphicon glyphicon-remove" onClick={ this.remove }></span>
        </div>
      </div>
      <div style={{ display: 'flex', alignItems: 'center', … }}>
        <div>{ this.props.content }</div>
      </div>
    </div>
  }
});

The render method creates a frame with a header and content determined by the header and content properties. The header includes a “remove” span that when clicked invokes the remove callback which is also a property (this.props.remove).

Notice how the outer div has its draggable attribute set to true. This enables HTML drag/drop operations, which we will discuss later.

The Tile component’s most interesting property is content, which represents the child component that contains the tile information. Our application defines nine types of tile content component, including charts, gauges, grid, etc. They all have a data property that is set by the parent component and contains the data to be shown on the tile.

Tile components may be as simple or complex as you like. Adding new tile types is easy: create the component to show the data in “props.data” in whatever way you want, and add the new tile type to the application component’s tileCatalog array.

Tile components may contain other components, including Wijmo data visualization controls. For example, here is the implementation of the BarChart tile component:

var BarChart = React.createClass({
  render: function () {
    return <Wj.FlexChart
      chartType="Bar"
      itemsSource={this.props.data}
      bindingX="date"
      axisX={{ format: 'MMM-yy' }}
      series={[
        { name: 'Sales', binding: 'sales' },
        { name: 'Expenses', binding: 'expenses' },
        { name: 'Profit', binding: 'profit', chartType: 'LineSymbols' }
      ]} />
  }
});

And here is the implementation of the Grid tile component:

var Grid = React.createClass({
  render: function () {
    return <Wj.FlexGrid
      isReadOnly={true}
      headersVisibility="Column"
      selectionMode="ListBox"
      itemsSource={this.props.data}
      columns={[
        { binding: 'id', header: 'ID', width: 40 },
        { binding: 'date', header: 'Date', format: 'MMM yyyy' },
        { binding: 'sales', header: 'Sales', format: 'c' },
        { binding: 'expenses', header: 'Expenses', format: 'c' },
        { binding: 'profit', header: 'Profit', format: 'c' }
      ]} />
  }
});

The main advantage of the React implementation of this app is the neat encapsulation of the tile components. Each one is represented by a single TSX file that contains the logic and UI.

Dragging Tiles

We have shown how users can customize the dashboard by adding new tiles or removing existing ones. The part that is missing is the use of drag and drop to reorder tiles, which was one of the main initial requirements for the app.

We already had this code written for the Angular version of the app. Fortunately, the code used standard HTML5 drag/drop functionality which was very easy to port to React. This was done by moving the original drag/drop code into a method called enableItemReorder and calling that from the main component’s componentDidMount method:

componentDidMount() {
  // enable tile drag/drop
  var panel = document.querySelector('.dashboard');
  this.enableItemReorder(panel);
},

The enableItemReorder method adds handlers to the standard “dragstart”, “dragover”, and “drop” HTML5 events.

Because the HTML drag/drop events work with the actual HTML elements on the DOM (and not with the React virtual DOM), we must update the state when a drop operation is finalized. This is done when handling the “drop” event, as shown in the code snippet below:

enableItemReorder(panel) {
  var dragSource = null,
      dropTarget = null;
  // add drag/drop event listeners
  panel.addEventListener('drop', (e) => {
    if (dragSource && dropTarget) {
      // re-order HTML elements (optional here, we're updating the state later)
      var srcIndex = getIndex(dragSource),
          dstIndex = getIndex(dropTarget),
          refChild = srcIndex > dstIndex ? dropTarget : dropTarget.nextElementSibling;
      dragSource.parentElement.insertBefore(dragSource, refChild);
      // update state
      var tiles = this.state.tiles.slice();
      tiles.splice(srcIndex, 1);
      tiles.splice(dstIndex, 0, this.state.tiles[srcIndex]);
      this.setState({ tiles: tiles });
    }
  });

The final piece is touch support. Since the code relies on native HTML5 drag/drop events, we added drag/drop touch support simply by including the DragDropTouch polyfill in our project.

The screenshot below shows the running application, with a tile being dragged into a new position:

03_dynamicdashboard_react

Conclusion

Porting the Dynamic Dashboard sample to React was surprisingly easy given the relative complexity of the app. Creating new tiles of arbitrary types, supporting drag/drop operations, and encapsulating arbitrary components within tiles are not trivial tasks.

In my opinion, the most significant benefits of using React in this sample were:

  • The ability to use TSX and get full design-time error checking, IntelliSense, and rich debugging for the entire app (including the TSX markup!).
  • The clean state-driven architecture imposed by React (which may take a little getting used to, but tends to pay off later).
  • The ability to encapsulate tiles neatly into single-file components.

The Dynamic Dashboard sample could be used as a starting point for actual dashboard apps. Obvious missing features are:

  • The ability to save and restore dashboard layouts to local storage.
  • Adding state to tiles so they can be customized by users.

To learn more about Wijmo, please visit our home page. To learn more about using Wijmo in React applications, please visit our React page.

View the sample

The post How to Create a Dynamic Dashboard in React appeared first on Wijmo.

How to add HTML5 Report Viewer to a Web App

$
0
0

C1 Web API Report Services enables you to build HTTP services, which can be consumed by a variety of clients for viewing, loading and caching reports, including the Wijmo ReportViewer. These are REST-based API services, which communicated with HTML 5 ReportViewer control to display the report content on the web.

Available as Visual Studio template, C1 Web API enables you to create report services on Visual Studio. Client applications send a request to the report services application to load reports, export reports, and allow user to use parameters in the report. The service supports exporting your reports to PDF, Excel, HTML, RTF, OpenXML, and Image. 

01_diagram

Set up report services for the report viewer

Create a report services application by C1 Web API Project Templates in Visual Studio:

  1. Installed ASP.NET Web API Edition from here.
  2. Select a C1 Web API Application template in Visual Studio New Project dialog:

    02_visualstudiotemplate

  3. The project template wizard shows. Please check Report services and click OK:

    03_projectsettings

  4.  Add reports to this web application.
  • FlexReport or C1Report:
  1.  Copy the report definition file to the application. Please also copy the related database file and update the connect string of the report if necessary.

    04_reportdefinition

  2. Add a FlexReport disk storage in Configure method of Startup. For example:
    app.UseReportProviders().AddFlexReportDiskStorage("Root", System.IO.Path.Combine(System.Web.HttpRuntime.AppDomainAppPath, "ReportsRoot"));
  • Regarding SSRS reports: please register an SSRS report server in Startup:
    app.UseReportProviders().AddSsrsReportHost("ssrs", "http://ssrshost/ReportServer", new System.Net.NetworkCredential("username", "password"));
  • Run the application in VS, or publish it in IIS.
  • Wijmo’s ReportViewer has been launched as a control, and is available with Wijmo Enterprise. You’ll be able to view FlexReports in ReportViewer, and in order to generate a FlexReport—and connect the ReportViewer to the FlexReport— you’ll need GrapeCity’s Ultimate suite. Ultimate includes the code-free standalone report designer, FlexReport Designer, along with a Web API.

    Read more about GrapeCity’s Ultimate suite

    The post How to add HTML5 Report Viewer to a Web App appeared first on Wijmo.

    Wijmo 2016 v3 Has Landed!

    $
    0
    0

    We’re pleased to announce the third major release of Wijmo in 2016!

    Download Wijmo V3 2016

    Interop Enhancements

    Wijmo has continued to expand interop to include Angular 2, ReactJS, and VueJS.

    Module Support

    Wijmo was originally designed as a single module. Everything was stored in the wijmo namespace. Wijmo now includes many different module flavors so that it is more easy to use with different module loaders. When downloading Wijmo, you get wijmo’s scripts as AMD modules, CommonJS modules and SystemJS modules. With these modules you can easily use wijmo in WebPack, AngularCLI, etc.

    Wijmo also includes NPM images with each of these module formats. This allows you to run “npm install” from a local NPM image on disc. We are hoping to one day support the public NPM registry as well.

    Learn more: Integrating Wijmo Controls with Module Loaders and Bundlers

    Angular 2 Support

    Not only is Wijmo committed to Angular 2 support, but we have interop libraries for many JavaScript frameworks. Learn more about Angular 2 support or about FlexGrid, the best data grid for Angular 2.

    ReactJS Support

    Wijmo is dedicated to interop in any framework. This release contains official support for ReactJS, and you can use Wijmo controls in any ReactJS application as React components.

    ReactJS Interop sample | How to Use Wijmo in ReactJS Apps blog | ReactJS DyanmicDashboard sample | How to Create a Dynamic Dashboard in React blog

    VueJS Support

    VueJS is another framework gaining traction. Many customers have requested VueJS support in Wijmo. This release offers official support of VueJS 1.x and 2.x. You can use Wijmo controls in any VueJS application as Vue components.

    VueJS Interop sample | How to Create Great VueJS applications Using Wijmo Controls blog

    ReportViewer

    This release includes a ReportViewer control in our new wijmo.viewer module, included in Wijmo Enterprise. The ReportViewer is used to display reports from a FlexReport server. FlexReport is a .NET reporting solution that can render SSRS reports as well as migrate Crystal Reports and C1Reports. The ReportViewer calls a web API that renders the document and sends it back in a format for being displayed in an HTML5/JavaScript application.

    The Wijmo ReportViewer has a wide array of features like: thumbnail display, scrolling or paged reports, zooming, printing, exporting and more. Best of all, ReportViewer can render reports on mobile devices.  

    To use the ReportViewer, you will need FlexReport, which is included in GrapeCity’s Ultimate suite. Purchasing Ultimate will give you access to all Wijmo controls as well as FlexReport and more.

    wijmo_01_reportviewer

    ReportViewerIntro Sample | ReportViewer Tutorial

    PDF Viewer (Beta)

    Similar to our new ReportViewer control, we are providing a Bea version of a new PdfViewer control. It is also included in the wijmo.viewer module, included in Wijmo Enterprise. The PdfViewer control displays PDF files that are render on the server using C1 Web API PDF Services (.NET).  

    To use the PdfViewer, you will need C1 Web API PDF Services, which are included in GrapeCity’s Ultimate suite. Purchasing Ultimate will give you access to all Wijmo controls as well as PDF Services and more.

     

    wijmo_02_pdfviewer

    PdfViewerIntro Sample (Beta)

    FlexGrid Validation

    We added data validation to the CollectionView class, which can be used by all Wijmo controls that support data collections, including the FlexGrid.

    To add validation support to a CollectionView, set the new getError property to a callback function that takes a data item and a property name as parameters, and returns a string with an error description (or null if there are no errors).

    wijmo_03_olapshowas

    Validation Sample | Data Validation in FlexGrid Blog

    OLAP ShowAs

    At the request of our customers, we have added more options to our showAs field setting in our OLAP PivotPanel.

    We added five new settings to the wijmo.olap.PivotField.ShowAs enumeration: PctGrand, PctCol, PctRow, RunTot, and RunTotPct. These new settings are compatible with similar settings available in Excel. Take a look at the new feature in the OlapShowAs Sample.

    wijmo_03_olapshowas

    FlexGrid Footers

    We’ve added support for column footers in FlexGrid. Easily add custom footers to columns using the new columnFooter in FlexGrid. Take a look at this new feature in the FlexGrid Custom Footers sample.
    wijmo_04_flexgridfooters

    New Chart Types

    We have a new Box Plot chart type for creating Box & Whisker charts. It is included in the wijmo.analytics module and implemented as a series. Take a look at the new box plot chart type in the FlexChartAnalytics sample.

    wijmo_05_flexchartanalytics

    This release includes a new FlexRadar chart control that can be used to create radar-type charts. Take a look at the new FlexRadar Intro sample.

    wijmo_06_radar

    We also added a funnel chart type to FlexChart. Take a look at the new funnel chart type in the FlexChart Intro sample.

    wijmo_07_funnel

    New Help System

    Last, but not least, we’ve completely rebuilt and redesigned our online documentation. The redesign includes better content, layout, navigation, search and much more. Take a look at our new online documentation.

    wijmo_08_help

    New Samples

    Use the SampleExplorer to search, filter by framework and even browse source code for all of our samples.

    Breaking Changes

    • Changed the arguments of the cellEditEnding event from CellRangeEventArgs to CellEditEndingEventArgs, which extends the former with a ‘stayInEditMode’ member. Any code that calls the onCellEditEnding event raiser should be updated as follows:
    // raise grid's cellEditEnding event
    //var e = new wijmo.grid.CellRangeEventArgs(grid.cells, this._rng);
    var e = new wijmo.grid.CellEditEndingEventArgs(grid.cells, this._rng);
    grid.onCellEditEnding(e);
    
    • FlexSheet: Changed .wj-header-row font and background colors. To get old styles reset values to: background-color: #4800ff !important; color: #ff6a00 !important;

    Change Log

    "dependencies": {
    "wijmo": "http://prerelease.componentone.com/wijmo5/npm-images/C1Wijmo-Enterprise-Eval-AMD-5.20162.222.tgz",
    ... another libraries
    }
    

    Due to this change, the samples from Wijmo Enterprise Evaluation build can be freely moved to a new location now without a necessity to correct Wijmo reference in package.json.

    • Added external module versions of Wijmo core modules. Wijmo download zip now includes NpmImages folder with the wijmo-amd, wijmo-commonjs and wijmo-system subfolders containing Wijmo modules in AMD, CommonJS and System formats respectively. Each of these folders is effectively an NPM image that can be installed using the npm install [path to a folder] command. Alternatively, a corresponding record can be added to an application’s package.json file that will cause Wijmo installation from a local folder to the application’s node_modules/wijmo folder, when "npm install" command is executed in the application’s root folder. For example:
    "dependencies": {
    "wijmo": "../../../../../NpmImages/wijmo-amd",
    ... other libraries
    }
    

    Currently only Wijmo core and Angular 2 interop modules are represented as external modules in these folders, the rest of interops are shipping as conventional global modules. The culture files (wijmo.culture.[culture_code]) are global modules too, and should be used in conjunction with Wijmo external modules in the same way as they are used with global modules – by adding them to HTML page using <script> tag, or in dynamic scenarious by loading them using XMLHttpRequest.

    One important remark regarding Angular 2 interop modules: Those were external modules from the day one, and referenced Wijmo core modules via global ‘wijmo’ variable (e.g. wijmo.grid.FlexGrid). The Angular 2 interop modules under the NpmImages folder are different: they reference Wijmo core external modules using the TypeScript "import" statement (that transpiles to the appropriate JavaScript code depending on the current module format). For example:

    import * as wjcGrid from 'wijmo/wijmo.grid';

    Module names follow the same convention as Angular 2 interop modules, i.e. ‘wijmo/’ prefix followed by a module name, e.g. ‘wijmo/wijmo’, ‘wijmo/wijmo.input’, ‘wijmo/wijmo.grid’. Wijmo Angular 2 samples are reworked to use external versions of Wijmo core modules. Their package.json file includes a reference to the NpmImages/wijmo-amd folder (as shown in the example above) that causes an automatic installation of all necessary Wijmo code in the node_modules/wijmo folder when you issues an "npm install" command.

    Note that this definition works only if you use it from its original location in the Wijmo zip image. If you move a sample to a new location then you need to correct this path in the sample’s package.json. The rest of the samples continue to use conventional global modules. Integrating Wijmo Controls with Module Loaders and Bundlers

    • Added a new wijmo.viewer module that includes two controls:
      • ReportViewer: displays server-side generated FlexReport and SSRS reports.
      • PdfViewer: displays PDF files using a server-side service.
    • Improved support for filtered DataMaps with duplicate display values
    • Added ability to export the FlexGrid.columnFooters panel to PDF (TFS 208282).
    • Added ‘showFilterIcons’ property for FlexSheet. User is able to show/hide the filter icons in the Column Header of FlexSheet by this property. (TFS 214354)
    • Added ability to skip columns of FlexGrid during exporting to Excel. (TFS 195426)
    • Add word wrap support for saving/loading xlsx file. (TFS 205565)
    • Replaced character-based pencil and asterisk icons used to indicate edit mode/new template in FlexGrid rows with new glyphs: "pencil" and "asterisk". This makes it possible to hide or customize the icons using CSS.
    • Added FlexGrid.rowEditStartingStarted events to complement the rowEditEnding/Ended events which were already available. Also made rowEditEnding/Ended events fire when canceling edits. These changes make it easier to implement custom behaviors such as edit mode indicators and deep-binding edit undos.
    • Improved FlexGrid.beginningEdit event parameters to set the "data" event parameter to the event that caused the grid to enter edit mode (usually a keyboard or mouse event, or null if the editing was initiated by a call to the startEditing event)
    • Improved FlexGrid column auto-generation to handle fields that contain null values
    • Added Vue2 interop (wijmo.vue2.js) https://vuejs.org/2016/04/27/announcing-2.0/
    • Added support for wijmo.olap controls to Vue/React interops
    • Added Vue/React versions of the OlapIntro sample

    Download Wijmo V3 2016

    The post Wijmo 2016 v3 Has Landed! appeared first on Wijmo.

    Rethinking the Periodic Table with Wijmo’s Sunburst

    $
    0
    0

    Designed to ease the process of visualizing hierarchical data, sunburst charts display categorical data “tiers” followed by the data points themselves radiating out from a central point. To put it more simply, sunburst charts portray data as categorized arcs. Conveniently, Wijmo 5 now ships with a Sunburst control that makes it easy to visualize data as a sunburst chart on the web. In this blog, we’ll adapt a .NET demo to display the periodic table of the elements as a sunburst chart on the web using only Wijmo and JavaScript (JS).

    View the New Sunburst Periodic Table

    Get the Sample on GitHub

    Before we go any further, let’s take a look at the finished product. Be sure to keep this in mind while moving through the tutorial so we can visualize the objective we want to reach.

    An animation showcasing the final Periodic Sunburst data visualization's function

    Now that we’ve visualized what we want our final to product to look like and do, let’s talk about why we would even want to do something like this and then how we can make it come to life.

    What’s Wrong with the Periodic Table?

    Hopefully you’ve keyed into the mind of a data visualizer by now and are asking the question I stressed so much a little bit ago: why? There’s already a perfectly good, working periodic table of the elements out there, and many of us have been familiar with it for a good portion of our lives. So why change it?

    As a former biochemist, I can sympathize with anyone who’s trying to learn the periodic table for the first time or trying to relearn it as an adult. As we all know, the traditional structure isn’t exactly the most intuitive. To a seasoned chemist or other basic science professional, the layout of the traditional periodic table makes perfect sense and is, in fact, very useful. To someone simply using it for reference or looking at it for the first time, however, its organization is often a mystery.

    So that’s what’s “wrong” with the traditional periodic table: it was designed for chemists, not teachers or students, or really anyone else for that matter. That’s why Wijmo’s Sunburst can help us here: it’ll let us display elements grouped by their properties in a visually obvious way.

    A traditional periodic table designed for children with color coded groups.

    A traditional periodic table designed for children with color coded groups.

    Building the Periodic Sunburst

    Before we get started, I want to point out that this tutorial doesn’t walk through every single step of the process. Although this is designed to be a complete project tutorial, our focus here is to demonstrate how we can link up datasets with the Wijmo Sunburst chart. If you want to view the complete project, it’s available on GitHub.

    Step 1: Initializing the Project

    As it goes in web development, there will be a near infinite amount of ways to set up this project. There are a number of frameworks, libraries and even programming languages that can be applied to solve this problem.

    That being said, I’m going to use vanilla (pure) JavaScript throughout the tutorial to make this transferable to any other JS-based solution. I also want to point out just how powerful and adaptable the Wijmo Sunburst control is. Look for notes pointing out sections where a framework or library would be useful, and rest assured that another tutorial focusing on building this project with a MVC framework is in the works.

    Next, I’ll talk about the project design considerations and how I approached them, but you can move on if you just want to check out the code.

    Aside from that consideration, there are a few other things to think about when setting up this project:

    1. We’re going to be loading JSON from a file. The easiest pure JS way to do this is by using an XMLHttpRequest (XHR). Since XHRs don’t work on the local file system, we’ll need a new way to test locally.
    2. We’re going to be writing a lot of data handling and access logic as well as view logic. I know, I know, JS isn’t technically object-oriented, but wouldn’t it be better to compartmentalize our code somehow?
    3. Since we want to walkthrough building a production-ready project from start to finish, how can we minify and package our files for production?

    I thought about each of these issues and tried to come up with a solution that would leave the tutorial accessible to everyone while also providing a full-fledged, standalone solution. You can read more about the full details in the project README, but here are my solutions in brief:

    1. If you don’t have a development web server set up, I recommend using Apache. It’s quick, easy, and that’s what I’ll be using for all of my testing, just to allow XHRs to load the JSON data.
    2. I’ve decided to write the logic for this project using JavaScript modules. Specifically, I’m going to use CommonJS module syntax and patterns. Because of this, I’m also using Browserify to package all of the modules into a single JS file for production. Browserify is easiest to use with js and NPM, so I’ll also be using those as dependencies.
    3. Even though I’ll be writing code in vanilla JS, I use a lot of new ES6 syntax. To minify JS files, I’m using babili since it supports ES6.

    So that’s pretty much it for my development dependencies! Again, you don’t have to use any of these, but I just wanted to give an overview of how I’m approaching things.

    Step 2: Setting up the Data Source

    To build out a new visualization of the periodic table, we’ll need data on the elements including their types so that we can correctly categorize them. Ultimately, we want this to be in JSON format so we can easily and natively work with and manipulate the data in JavaScript.

    Below, I’ll walk through the steps of downloading and cleaning the data from scratch, but if you want the final version you can grab it from GitHub.

    • Fortunately for us, Data Explorer offers a free dataset that is almost exactly what we need. The big caveat here is that Data Explorer provides their dataset in XML format with some extra schema information that we don’t need. Before we take care of that, though, let’s download the data.
    • Next we’ll convert the XML data we downloaded to JSON using a free online converter. Once we have the JSON representation of the data, we’ll save it in a file so we can clean things up a bit.
    • Now we have to trim away the excess schema information so we’re left with only a single root JSON entity that holds an array of element entities.
    • Lastly, believe it or not, some of the data provided by Data Explorer is little bit off! We’ll make some small corrections and save our final dataset.

    Step 3: Building the Data Access Layer (DAL) and Data Model

    Now that we have our cleaned-up data accessible to us, we have to build out the logic to load it and parse it. Just as it seems, this will require a two-step process in which we (1) load the JSON data from Step 2 into a JS object and (2) parse out the array of element data into formal Element objects and categorize them into Group and SubGroup objects as well. The second step can be broken down even further, as we have to develop a data model and an adapter to load data into it.

    Let’s start by building a utility to actually pull JSON from the file.

    JsonDataLoader.prototype.getObjectFromJson = function (jsonFilePath, callback) {
        readFileContents(jsonFilePath, function (eventArgs) {
             callback(JSON.parse(this.responseText));
        });
    };
    

    This is the most important function in the data loading module. It takes a file path and a callback function as arguments, and uses the below helper function to load the JSON then returns it as an object:
    function readFileContents(filePath, callback) {
        let reqClient = new XMLHttpRequest();
        reqClient.onload = callback;
        reqClient.open("get", filePath, true);
        reqClient.send();
    }
    

    And that’s it! We can now use these functions by requiring the JsonDataLoader module in any other code and using the getObjectFromJson function. If you want to see the full file contents and more documentation, follow the link up above. That goes for any code we talk about in the rest of the article, too!

    So now that we can load the data from a file, we need a model to store it in. Onto building the data model!

    Before we dive in, let’s conceptualize what we need to build. Ultimately, we want (as the finished product picture showed) a model containing root “group” nodes which contain “subgroup” child nodes which contain elements as terminal nodes. Briefly, that equates to something like this:

    Periodic Sunburst Data Model Schematic

    A schematic representation of the data model necessary for building the Periodic Sunburst

    So how do we enact that structure in our code? It’s probably easiest to just see it in action, so let’s get to it!

    var Element = function (elementJObj) {
        this.atomicNumber = elementJObj.properties['atomic-number']; // this and atomic-weight must be accessed using bracket notation because they have hyphens
        this.atomicWeight = elementJObj.properties['atomic-weight']; // this and atomic-weight must be accessed using bracket notation because they have hyphens
        this.elementName = elementJObj.properties.element;
        this.eleSymbol = elementJObj.properties.symbol; // rename this to eleSymbol since symbol is a reserved keyword in ES6
        this.type = elementJObj.properties.type;
        this.value = 1; // Set a uniform value that can be bound when initializing the chart to get equal arc angles
    };
    

    In Element.js, we just want to build a constructor that can take an element entity right from the JSON object and convert it into something more useful. It’s also important to note the final property setter:
    this.value = 1
    This gives each Element object a property equal to the same numeric value which will be important later for rendering our Sunburst chart.

    var SubGroup = function (subGroupName) {
        this.subGroupName = subGroupName;
        this.elements = [];
        this.characteristics = '';
    };
    

    In SubGroup.js, all that really matters is that we store a name property and set up an empty array that will ultimately hold Element objects. One “bonus” property that we set up here is the characteristics property. Eventually, this will hold a string representation of characteristics that we can display to the user.

    var Group = function (groupName) {
        this.groupName = groupName;
        this.subGroups = [];
    };
    

    Even simpler than the SubGroup module, Group.js simply holds a constructor that takes a name and sets up an empty array for holding SubGroups.

    The data model is all written and assembled now, we just have to load data into it! The last step is to write a data adapter that can take the raw data loaded from JSON and put it into the model we just created.

    As it would be a little overwhelming to post the entire DataSourceAdapter module here, follow the link above to view the documented code on Github. The primary function in this module is

    DataSourceAdapter.prototype.getChartDataSource = function (callback) { ... }
    which loads the element data using our JsonDataLoader utility module, parses it, and returns an array of Group objects.

    I highly recommend taking a look at the module to see exactly how the final data structure is generated, but the important result is that we are given an array of Groups which each contain SubGroups which each contain Elements. This can be directly loaded by our Sunburst chart in the view.

    And with that, we have a working data layer that can interface directly with our Sunburst chart!

    Step 4: Building the View and Displaying the Sunburst Chart

    The first step in displaying our Sunburst Chart in the view is by giving it a DOM host element in index.html:

    <!-- The main container where the Sunburst control is rendered -->
    <div id="periodic-sunburst" class="periodic-sunburst"></div>
    

    This gives us a DOM element to render the chart in, but it doesn’t actually handle any of the rendering. To generate the chart and place it in the element, we’ll initialize the control in the code-behind, contained in app.js:
    DataSourceAdapter.getChartDataSource(function (dataArray) {
    let mySunburst = new wijmo.chart.hierarchical.Sunburst('#periodic-sunburst'); // initialize!
        // Let the Sunburst Chart know we're going to start making changes
        mySunburst.beginUpdate();
        // Set some stylistic properties for the chart
        mySunburst.legend.position = 'None'; // hide the legend
        mySunburst.innerRadius = 0.3; // set up a relatively large space for displaying info
        mySunburst.selectionMode = 'Point';
        mySunburst.dataLabel.position = 'Center'; // center panel labels
        mySunburst.dataLabel.content = '{name}'; // the panel should display its name (derived from bindingName property)
        mySunburst.itemsSource = dataArray; // set the items source to the array generated by the DataSourceAdapter
        mySunburst.binding = 'value'; // bind each item to the constant 'value' property to get equal arc angles for all element panels
        mySunburst.bindingName = ['groupName', 'subGroupName', 'eleSymbol']; // set the property that gives the name we want to display for each chart level
        mySunburst.childItemsPath = ['subGroups', 'elements']; // set the property names that hold the children for each level (remember our data structure is Group.subGroups.elements)
        mySunburst.endUpdate();
    ...
    }
    

    The documented code above details the methods and properties we need to use to set up our Sunburst chart to get the final product we’re looking for. Especially important properties to notice are the itemsSource, binding, bindingName, and childItemsPath properties. These properties load the data we generated and formatted in Step 3, bind the arc sizing property for element panels to the uniform ‘value’ property, give the property names that the chart will look for to display data labels, and provide the property names for the arrays holding children, respectively.

    That alone should be enough to initialize the Sunburst chart and render it with all of the data we formatted into our model. But that’s really only half the job, right? If you think back to the demo we conceptualized earlier, we also want our Sunburst to display information about the selected object in the center. So how do we go about doing this? Just like with everything else, let’s break it down into steps:

    1. Handle click events on the chart (app.js)

        // Set up a function to listen for click events on the Sunburst Chart's parent DOM element
        mySunburst.hostElement.addEventListener('click', function (e) {
            // Perform a hit test to get a clicked panel's name then use it to set up the info panel via the ViewAdapter
            let ht = mySunburst.hitTest(e.pageX, e.pageY);
            myPropTile.showInfoPanel(ViewAdapter.getObjectFromChartName(ht.name, mySunburst.collectionView));
        });
    

    When the chart’s host DOM element is clicked, we’ll use the handy built-in Sunburst method of hitTest() to find out the name of the panel that was clicked. Next, we pass this name and the Sunburst’s collectionView to a function in the ViewAdapter module that maps the name to the proper Group, SubGroup or Element object. Finally, we get an object representation of what was clicked, and can use that to show the properties we’re looking for.

    2. Send the clicked Object to myPropTile and show the properties (lib/view/PropertiesTile.js)
    So what exactly is myPropTile? It’s simply an instance of the PropertiesTile object wrapped around a DOM element. The PropertiesTile module contains an important function, showInfoPanel that initializes and displays the correct property tile.

    Once the PropertiesTile is instantiated and hooked up to the DOM events we need to listen on, we’re done! There are quite a few intricacies around how the PropertiesTile works, and I encourage you to check them out in the source code.


    That about does it for all of the core functionality of our data visualization! As you’ll find in the GitHub repo, there are some additional steps taken that aren’t covered in-depth here. These include everything from creating a shim for browser compatibility to theme generation with CSS. I encourage you to take a look at the source code holistically to get a better understanding of the overall project.

    If you have any questions about this project or the Wijmo Sunburst Chart in general, don’t hesitate to let me know in the comments or by sending me an email. I’ll be actively and openly responding to all feedback, so don’t be shy!

    Thanks so much for reading, and I hope you enjoy!

    Download the source code for this sample: v0.1.1 Release (zip / tar)

    View the New Sunburst Periodic Table

    The post Rethinking the Periodic Table with Wijmo’s Sunburst appeared first on Wijmo.


    Wijmo Usage Survey 2016

    $
    0
    0

    Dear customers and evaluators, we have always and will always want feedback from you. Our roadmap is customer-driven and your input is needed. Please take 2 minutes to complete the Wijmo Usage Survey. The answers will drive our focus and future development.

    Take the Wijmo Usage Survey

    We want to know which controls you are using most, which extensions you use and which frameworks and tools you use alongside Wijmo.

    Thanks for taking the time to help influence our roadmap.

    The post Wijmo Usage Survey 2016 appeared first on Wijmo.

    Last Chance to Save on JavaScript, .NET, and Native Mobile controls

    Wijmo Roadmap for 2017

    $
    0
    0

    It’s hard to believe another year of Wijmo has gone by. 2016 was another productive year of development and growth for the Wijmo team. Looking back at our 2016 roadmap, you can see that we delivered everything that we promised. Let’s recap some of 2016’s highlights:

    Most of what we focused on in 2016 was based on you, our customers. Our roadmap is always customer-driven, and 2017 will be no different. We spend a lot of our time working with our customers to understand their use cases and needs. Many of our customers request controls or features directly. We work with them to create requirements, build a prototype and get feedback before releasing publicly.

    Key Points

    In 2017, we’re focusing on:

    • Polishing controls based on customer needs, including performance, features, and fixes.
    • Make Wijmo easier to use by improving: tutorials, guides, samples and documentation.
    • Adding some major new controls, such as TreeView, PdfViewer and Forms.

    TreeView

    thumbnail_tree4

    Multiple customers have asked for a TreeView control this year. We currently have a TreeView in development that will be releasing in early 2017. Our TreeView will include checkboxes, icons, drag and drop support and more.

    PdfViewer

    We recently released a preview of our PdfViewer control. The PdfViewer uses a server-side engine to render PDFs and send SVG to the client for display in the viewer. Our PdfViewer will ship in mid-2017.

    Server-side OLAP

    Our OLAP controls are very powerful and can handle a large amount of data with great performance. However, some scenarios require a server-side OLAP engine to handle the processing of millions of records. The server-side OLAP engine will ship in mid-2017.

    Continued Improvements

    As usual we will be continuing to improve all of our controls, specifically targeting performance. We will also be continuing to fix bugs based on customer reports. I expect that we will be adding some features to FlexGrid and FlexChart based on customer requests as well.

    Experimentation

    While we’ll be focusing most of our efforts on shaping Wijmo 5 around our customers, we still reserve some time for fun. By fun, I mean pushing our controls to the limits of the browser. After all, Wijmo 5 was born from experimentation in ECMAScript 5.

    • We’ll be trying out some emerging capabilities in browsers to see how fast we can make Wijmo.
    • We will be experimenting with WebWorkers to see if we can improve application responsiveness while some control do heavy processing.
    • Another area of experimentation is TypeScript. We want to try out some new features, like private members in our code base. We also want to utilize some new ECMAScript 6 feature as they become supported. Using TypeScript as our source code helps us easily do that.

    We look forward to working with you in 2017!

     

     

     

    The post Wijmo Roadmap for 2017 appeared first on Wijmo.

    Wijmo Build 5.20163.254 Available

    $
    0
    0

    We just released Build 254 and it has some nice new features as well as a long list of bug fixes.

    Change Log

    • Angular 2: Added support for Angular 2.4.1 Angular 2 Info
    • ReactJS: Added support for ReactJS ReactJS Info
    • VueJS: Added support for Vue 2 VueJS 2 Interop sample | How to Create Great VueJS applications Using Wijmo Controls blog
    • Added PeriodicSunburst sample. PeriodicSunburst sample | Rethinking the Periodic Table with Wijmo’s Sunburst blog
    • Improved FlexGrid performance when binding to large collections and not limiting grid height (automatically sized grids). This used to cause poor performance since the grid only took its host element into account when virtualizing cells; now it also takes into account the browser window.
    • Improved FlexGrid clipboard support to handle cells with line breaks.
    • Added a FlexGridDetailProvider.isAnimated property to enable animated transitions when showing row details.
    • Improved FlexSheet support to copy/paste the content of the HeaderRow in the bound sheet.
    • Added a Control.rightToLeft property that determines whether the control is hosted in an element with right-to-left layout.
    • Improved showPopup method to handle screen boundaries when reference is a point.
    • Added RTL support to LinearGauge and BulletGraph controls. The gauges now take RTL into account when rendering and handling the keyboard. The new behavior is compatible with the input element’s when type=”range”.
    • Wijmo *culture.js files can be loaded before wijmo.js now.
    • Added support for Angular 2 Ahead-of-Time compiler. .metadata.json files for Wijmo Angular 2 components are added to NpmImages’ subfolders. Check also Breaking Changes section.
    • Angular 2 specific properties (like isInitialized) and events (like ‘initialized’/valueChangedNg/etc) of Wijmo components are now exposed in class declarations in .d.ts and hence available for Intellisense.
    • Added a getCellElement method to the wijmo.grid.GridPanel class to retrieve the HTMLElement that represents a given cell in the panel.
    • Added Menu.show method to display the menu at arbitrary positions on the screen (context-menu style).
    • Added a twoDigitYearMax property to the culture calendar so users can control the threshold used for converting two-digit year strings into full years.
    • Added support for showing group *and* column headers in the MultiRow control. This is done by setting the collapsedHeaders property to null (rather than true or false).
    • FlexGridPdfConverter added support for FlexSheet.
    • Added support for dataMaps on Boolean FlexGrid columns.
    • Added a dataMap property to the wijmo.grid.filter.ColumnFilter class. This dataMap takes precedence over the owner column’s DataMap and is used to provide the strings displayed by the filter editors. For example, it can be used to change the strings displayed for Boolean column filters from ‘true/false’ to ‘yes/no’.

    New Samples

    Breaking Changes

    • @WjComonent decorator is removed from the library, because AoT compiler doesn’t support custom decorators.
    • A suffix in implementation names of Angular incarnations of Wijmo events has been changed from ‘Wj’ to ‘Ng’ (e.g. valueChangedWj became valueChangedNg). Note that these events was not officially documented and their direct usage was not presumed.
    • A suffix in implementation names of Angular property change events (intended to implement two-way binding) has been changed from ‘Ng’ to ‘PC’ (e.g. valueChangeNg became valueChangePC). Note that these events was not officially documented and their direct usage was not presumed.
    • Added an optional ‘fn’ parameter that was missing in the wijmo.removeEventListener method. This will only break code that called removeEventListener specifying all optional parameters, which should be rare. The change provides more control over event removal and consistency with the wijmo.addEventListener method.

    Get Started

    Download Wijmo build 5.20163.254

    The post Wijmo Build 5.20163.254 Available appeared first on Wijmo.

    How to export selected rows of FlexGrid to a PDF file

    $
    0
    0

    Recently, I received an inquiry about exporting selected data from a FlexGrid to a PDF document. I found this interesting. While we often brag about the amount of data the FlexGrid can hold, in this case,the user needed only a portion of the data.

    Wijmo supports exporting data to a PDF Document, but the wijmo.grid.pdf module does not support the ability to omit rows of the FlexGrid when saved to the PDF file. The saving process simply copies the data from the control in the browser to the PDF document. Only minimal changes can happen here—like changing the font or background color.

    Currently, the wijmo.grid.pdf module is based on PDFKit API, so to get the desired functionality, we would need to create our own API for a PDF generator specifically tailored to the FlexGrid. Since our specialty resides with UI controls, creating a new PDF API was out of the question.  However, it is still possible to get the desired outcome.

    The solution is simple: use two FlexGrids.

    One FlexGrid contains all the data, and the other contains the selected data to export. Having the second FlexGrid appear in the application defeats the purpose, so we can hide the FlexGrid by setting the ‘display’ property to ‘none’ in markup. In pure JS, the HTML should appear something like this:

    <div id="theGrid" style="width:100%;height:350px;"></div>
    <div id="hiddenGrid" style="display:none;"></div>
    

    To handle selection, I used a ‘boolean’ field to in my data objects named “exportRow”. There are other ways to do this, but this approach is the simplest. Rows with ‘checked’ checkboxes in the “Export Row” column are copied to the hidden FlexGrid just before the data is exported.

    Here is the Javascript code:

    function exportSelectedRowsToPDF() {
    // copy selected rows of #theGrid to #hiddenGrid
    if (hidden == null) {
    hidden = new wijmo.grid.FlexGrid('#hiddenGrid');
    }
    var grid_cv = grid.itemsSource;
    var new_cv = new wijmo.collections.CollectionView(grid_cv);
    for (var i = 0; i < new_cv.items.length; i++) {
    if (!new_cv.items.exportRow) {
    new_cv.removeAt(i);
    i--;
    }
    }
    hidden.itemsSource = new_cv;
    //export
    wijmo.grid.pdf.FlexGridPdfConverter.export(hidden, 'FlexGrid.pdf', {
    scaleMode: wijmo.grid.pdf.ScaleMode.PageWidth,
    exportMode: wijmo.grid.pdf.ExportMode.All,
    maxPages: 10,
    styles: {
    cellStyle: {
    backgroundColor: '#ffffff',
    borderColor: '#c6c6c6'
    },
    headerCellStyle: {
    backgroundColor: '#eaeaea'
    }
    },
    documentOptions: {
    info: {
    title: 'Sample'
    }
    }
    });
    }
    

    The post How to export selected rows of FlexGrid to a PDF file appeared first on Wijmo.

    Viewing all 89 articles
    Browse latest View live