Quantcast
Channel: Kendo UI Blogs
Viewing all 181 articles
Browse latest View live

Breeze.js And The Kendo UI DataSource

$
0
0

Hot on the heels of my post on creating a Kendo UI DataSource for a Backbone.Collection, Brandon Satrom and I built a quick hack to see what it would take to integrate Breeze.js with our DataSource.

DataSource All The Things

If you're not familiar with Breeze.js, it describes itself by saying "Rich data for JavaScript apps is a Breeze". Basically, it's a framework to abstract away all of the complexities of calling data APIs through JavaScript. It takes the complexity of understanding not only XHR objects away, like jQuery's ajax method, but also understanding data formats, query parameter formats, integration with specific back-end data sources, and much more.

The basic transport code

Like the Backbone.Collection integration, I'm going to build a custom data transport for Breeze.js. Instead of focusing on the basic CRUD features, though, I want to show some of the more advanced features of reading data: sorting and paging.

To get started, I need a DataSource wrapper that allows me to pass in the needed Breeze.js objects. The end result will be a custom transport that calls through to the Breeze objects through four basic methods: create, read, update, and delete. If you need further review or information on this, be sure to read my previous post on building a DataSource for a Backbone.Collection, and check out the documentation for DataSource transport.

BreezeDataSource

(function ($, kendo, breeze) {
  'use strict';

  // namespace for the extensions
  kendo.data.extensions = kendo.data.extensions || {};

  // constructor function for the custom transport
  function BreezeTransport(entityManager, endpoint){
    this.entityManager = entityManager;
    this.endPoint = endPoint;
  }

  // instance methods for the custom transport
  $.extend(BreezeTransport.prototype, {
    read: function (options) {
      // ...
    },
    create: function (options) {
      // ...
    },
    update: function (options) {
      // ...
    },
    destroy: function (options) {
      // ...
    }
  });

  // Create the custom DataSource by extending a kendo.data.DataSource
  // and specify an init method that wires up needed functionality.
  kendo.data.extensions.BreezeDataSource = kendo.data.DataSource.extend({
    init: function (options) {
      // build the transport and final options objects
      var breezeTransport = new BreezeTransport(options.entityManager, options.endpoint);
      options = $.extend({}, { transport: breezeTransport }, options)

      // Call the "base" DataSource init function and provide our custom transport object
      kendo.data.DataSource.fn.init.call(this, options);
    }
  });
})($, kendo, breeze);

The Breeze EntityManager is the core of what we work with, and is where an app will configure it's back-end specifics. Passing this in to our custom DataSource will allow all of Breeze's flexibility, but still give us the ability to query the data based on the parameters that the Kendo UI DataSource provides to the read method.

Reading data with EntityQuery

Once we have the custom DataSource and transport outlined, we can focus on read data through the EntityQuery object.

This object allows us to form the query that will be sent back to the API, and includes methods three methods that we'll use for sorting and paging:

  • orderBy
  • skip
  • take

These are common method and attribute names used for sorting and paging. The orderBy method is fairly self-explanatory in name. It allows us to sort the results by the configuration we specify. The skip and take methods, in combination, allow us to facilitate paging. These two methods might not be as obvious, though.

Skip, and take a page

When building a paged data source of any kind, paging can be facilitated with two simple parameters: skip and take. Any system that needs to use paging, then, can provide these parameters and end up with the data set that they expect. When a DataGrid or other page-enabled control says it wants page 2 of a data set, and each page is 10 records long, this gets translated in to the skip and take settings.

Given a page length of 10 and a request for page 2, we can do simple math to get the starting point of the data we want to show from the overall result set. Since we want page 2 of data and the page length is 10, we know that we need to skip the first 10 records... the first page of data. This can be calculated with a little bit of code, quite easily:

Calculating skip

var requestedPageLength = 10;
var requestedPageNumber = 2;

var skip = requestedPageLength * (requestedPageNumber-1); // => 10

We're subtracting 1 from the page number so that we can get the starting point of the second page of data, not the end point.

Even when we request page #1, then we don't want to skip anything - we want to start at the beginning of the record set. The formula still works for this scenario: 10 * (1-1) = 0, which says "skip zero records" or "start at the very beginning."

The take parameter of the skip/take combination is the actual number of records that we want to get - the reuested page length. This parameter tells the data source how many records to return, after it has skipped the number that we said to skip.

Take is the page size

var take = requestedPageLength;

The end result of the skip / take combination is a paging system that can be used by nearly any data source and page-enabled control or other code.

Reading paged and sorted data is a Breeze

Integration between Breeze and the transport read method is easy from here. The options parameter that is passed through the method contains three attributes: sort, skip, and take. We can apply these to the Breeze EntityQuery to get the paged and sorted data that has been requested.

Paged and sorted data with Breeze

read: function(options){
  var orderVal = "",
      sortOps = options.data.sort;

  // build sorting the way breeze understands it
  if (sortOps) {
    orderVal = sortOps.field + " " + sortOps.dir;
  }

  // build a query to get the sorted and paged results
  var query = new breeze.EntityQuery(endpoint)
      .orderBy(options.data.sort)
      .skip(options.data.skip)
      .take(options.data.take);

  // ...
}

Note that we're not just grabbing the raw sort value from the options.data.sort. Instead, we are taking the field and dir attributes from this and creating an orderBy configuration that Breeze understands.

Once we have those values applied, we can execute the query using the EntityManager that was supplied to the DataSource.

Executing a Breeze query

read: function(options){
  // ...

  breezeEntityManager.executeQuery(query).then(function(xhr){
    options.success(xhr.results);
  });
}

Executing a Breeze Query will result in a q.js Promise object, which can be chained in to a then callback that is called when the data finally returns from the server. Once the data has returned, we call options.success and pass the resulting data.

Using the BreezeDataSource

With the read-only BreezeDataSource set up, we can use it as we would any other DataSource for a Kendo UI control. We only need to configure a Breeze EntityManager to work with our API, and then pass that to our BreezeDataSource.

Using the BreezeDataSource

  // create a Breeze EntityManager and configure
  // it for the API that we are connecting to
  var manager = new breeze.EntityManager({
    dataService: new breeze.DataService({
      serviceName: 'data/',
      hasServerMetadata: false
    })
  });

  // create a BreezeDataSource
  var ds = new kendo.data.extensions.BreezeDataSource({
    entityManager: manager,
    endpoint: "products.json",
    pageSize: 10,
    serverPaging: true,
    serverSorting: true
  });

  // assign the DataSource to the grid
  $("#grid").kendoGrid({
    columns: [
      { field: 'ProductName', title: 'Name'},
      { field: 'Supplier.SupplierName', title: 'Supplier'},
      { field: 'Category.CategoryName', title: 'Category' }
    ],
    dataSource: ds,
    pageable: true,
    sortable: true
  });

This will produce a Kendo UI Grid with the data being read through Breeze.js

About the Author
is a Developer Advocate for Kendo UI, a developer, speaker, trainer, screen-caster and much more. He's been slinging code since the late 80’s and doing it professionally since the mid 90's. These days, Derick spends his time primarily writing javascript with back-end languages of all types, including Ruby, NodeJS, .NET and more. Derick blogs at DerickBailey.LosTechies.com, produces screencasts at WatchMeCode.net, tweets as @derickbailey and provides support and assistance for JavaScript, BackboneJS, MarionetteJS and much more around the web.


HTML5: 10 Provocative Predictions For The Future

$
0
0

For HTML5 developers and decision makers, the most important technologies right now are HTML, JavaScript, CSS, mobile platforms and devices and evolving HTML platforms (browsers and operating systems). But what does that mean in the real world? It means these 10 things in 2013:  

[Note, this article was originally published at Read Write Hack http://readwrite.com/2013/02/22/html5-10-provocative-predictions-for-the-future]

1. Rise Of HTML5 Mobile Platforms

HTML5 has played an increasingly important role building cross-platform apps for mobile devices. So far that has primarily been done using native “wrappers,” such as Cordova, which allow HTML and JavaScript to power apps on other native platforms (such as iOS and Android). This technique is called “hybrid” app development.

This year, though, a wave of emerging platforms will support HTML5 apps as a first-class citizen - no wrapper required! The biggest players will be Chrome OS, which is about to get much more attention from Google; Firefox OS, already scheduled to start shipping on low-end ZTE and TCL devices in Europe; Tizen, a new HTML-focused platform backed by many industry heavyweights, including Intel and Samsung; Ubuntu Phone, which brings the most popular flavor of Linux to phones, again with a HTML-centered ap strategy; BlackBerry 10, which puts HTML and JavaScript at the center of its next-gen app strategy; and Windows 8, which introduced a new HTML and JavaScript development model for it’s “Windows 8 style” apps.   One (or more) of these platforms is bound to succeed in 2013. My money is on Chrome OS and Tizen. With the backing of Google, a revamped developer and consumer push, and the broadest platform strategy (spans mobile and desktop), Chrome OS is very well positioned.

Tizen, meanwhile, enjoys broad industry backing from Intel, Samsung, NEC, Panasonic, Sprint, Huawei and Vodafone (among many others), and engineering stewardship in The Linux Foundation. It shows the most potential to challenge Android as the “more open” (read: more customizable) open source device platform, which should appeal to device makers.  

2. Made For Chrome(kit)

A growing number of sites are once again buildiing Web apps tested to work in only one browser. Like the “Made for Internet Explorer” badges of the 1990s, developers are now proudly advertising “Made for Chrome” in their apps. Not using Chrome? No guarantees.   This trend is likely to accelerate in 2013.   With a rapidly evolving, highlycapable browser platform that is available on virtually every major operating system (Windows, Mac, Linux, Android and kinda iOS), and a Webkit foundation that helps deliver a little extra compatibility with other non-Chrome browsers (like Safari and BlackBerry browser), developers are likely to conclude that the “good outweighs the bad” when it comes to building exclusively for Chrome.   In exchange for potentially alienating some users, developers building for Chrome can more aggressively leverage HTML5 APIs and save valuable development and testing time.  

3. IE10 Euphoria - And Pain

Internet Explorer 10 is widely regarded as a huge step forward for the venerable Microsoft browser. With more support than ever for Web standards, IE10 goes a long way to put Microsoft’s browser in the modern HTML5 conversation.   But as fast-updating browsers like Chrome and Firefox race forward through 2013, IE will once again be left looking old and slow. There is a glimmer of hope that Microsoft will evolve IE more quickly: The Microsoft-owned HTML5 Labs, launched originally in the IE9 days, is continuing to publish new “experimental” improvements for IE10 that make it an even more capable HTML5 browser. Baby steps, but still a good sign.  

4. The Death Of IE6, IE7 & IE8

While IE10 will be in the spotlight, the long death march for Microsoft’s older IE versions will continue. Only the most stubborn corporate environments (and China) still require IE6 support, and much of the world skipped IE7 anyway. If you haven't already stopped supporting IE6 and IE7, 2013 is definitely your year.   Dropping IE8 is a bit more of a stretch, but the pressure is on. Not only does IE10’s release make IE8 two versions old (often used as a “clean” support cut-off justification), but jQuery 2.0 will join Google Apps in cutting-off IE8 in 2013. By the end of the year, most developers will conclude IE8 is not worth their time.  

5. The Death Of Android 2.x

Until recently, it looked like we had another IE6 on our hands with Android 2.x (Eclair, Froyo and Gingerbread). According to Google’s own stats, as recently as mid-2012, these versions of Android (mostly 2.3.x) represented more than 90% of all Android devices in use, despite the fact that Google was already shipping Android 4+! Google was failing to keep its Android user base (and ecosystem) upgrading.   Fortunately, the 2012 holiday season seems to have broken the logjam. Usage of Android 4+ (Ice Cream Sandwich and Jelly Bean) surged to nearly 40% at the end of 2012. By the end of 2013, Android 2.x will likely account for less than 15% of the market, and Android developers will be able to shift focus to versions 4+.  

6. Responsive Design Goes Mainstream

So far, responsive design has remained on the fringes of Web development - something nice to do “if you have time."   That's about to change. With the lines between PCs and mobile devices increasingly blurred, developers will have no choice but to develop websites and apps that can dynamically adapt to an unpredictable array of screen sizes and resolutions.

To ease the way, look for new techniques and defacto standards to also emerge, offering guidance for properly dealing with different device capabilities and form factors.  

7. Mobile Development Overtakes Desktop

It doesn’t take an expensive analyst to see the growth in phones and tablets while traditional PCs fade. Right now is the moment when developers will begin spending more time developing software for mobile devices than for traditional desktop PCs, extending from the consumer market to businesses of all sizes, for both internal and external audiences. If you’re not developing for devices in 2013, you’re either A) maintaining legacy software, or B) missing the boat.  

8. HTML On The Desktop

Just because mobile is on the rise, don’t start writing an obituary for desktop development. The traditional desktop form factor will remain critical for many information workers. But as the PC becomes one among many screens, developers will look for ways to write code that can be shared across the PC and mobile devices.   HTML and JavaScript are perfectly positioned to offer this capability, and platforms like Chrome Packaged Apps and Windows Store Style (WinJS) apps will make this possible. With both Microsoft and Google pushing HTML for desktop app development, developers will take notice and start embracing cross-platform desktop development with HTML and JavaScript.  

9. SPA Time

With the shift of desktop development and increasingly complex mobile apps to HTML and JavaScript, developers will recognize the need for new techniques to build maintainable cross-platform apps. The “Single Page Application” (or SPA) has been on the rise thanks to powerful frameworks like Backbone,Knockout and even Kendo UI. If “RIA” (Rich Internet Applications) was the buzzword in 2010, “SPA” will be the buzzword in 2013.   If you’re looking for the one new technology or concept to learn as an HTML and JavaScript developer in 2013, it's SPA architecture.  

10. HTML Gets Naked (Again)

Now that the W3C has “finalized” HTML5, public conversation and media coverage is going focus on what’s next for the Web standards platform. The W3C is already working on HTML 5.1, the next “snapshot” of the “living standards” work done within WHATWG, the Web Hypertext Application Technology Working Group. But as we move past the “HTML5” bubble, we’ll once again settle-in to talking about HTML, sans version numbers. After all, who wants to talk or write about “HTML5.1” or “HTML5.3”?   Whatever it’s called, the next wave of HTML platform improvements will shift focus beyond the lower-level core at the center of HTML5 (DOM elements, CSS styles, Simple JavaScript APIs like Geolocation) and instead characterize improvements that are important to more robust application development (like ShadowDOM, Web Components, CSS layouts, speech recognition and more).

The HTML conversation (and technology) will continue to evolve, even if the version numbers don’t come along for the ride.

About the Author
is an avid HTML5, CSS3, and JavaScript advocate, and geek about all things web development. He is an active speaker and author, helping developers around the world learn and adopt HTML5. Todd works for Telerik as VP of HTML5 Web & Mobile Tools, where his current technical focus is on Kendo UI. Todd is @toddanglin on Twitter.

Kendo UI Mobile and Windows Phone 8

$
0
0

In the roadmap update post for Q1 2013, I announced that, among other things, our first release of the year would include Kendo UI Mobile support for Windows Phone 8. With tomorrow’s Q1 Beta, you’ll finally be able to get hands on and start building Kendo UI Mobile apps that target Microsoft’s latest flagship phone OS.

Before you grab the Beta, though, I wanted to share more about what you can expect out-of-the-box with Kendo UI Mobile for Windows Phone 8. I’ll begin at the very beginning, with a brief recap of the goal of Kendo UI Mobile, and how this goal informs our mobile device support across all platforms.

The Goal of Kendo UI Mobile

Since our first release in Q1 of 2012, the goal of Kendo UI Mobile has been to enable developers building mobile web and hybrid–packaged for store deployment using a tool like Icenium–applications to use HTML, JavaScript and CSS, while providing a visual experience that automatically adapts to look native for a given platform. When all is said and done, we want Kendo UI Mobile to be the tool of choice that developers use to target multiple device platforms with a common web codebase. We enable that via two key Kendo UI Mobile features:

Feature #1. Device-specific themes that mimic key UI and UX for each platform we support.
Feature #2. Mobile-specific HTML/JS widgets that work well on every platform we support.

If you’ve used Kendo UI Mobile in the past, or walked through the demos at the Kendo UI Dojo or demos.kendoui.com, you’ve seen these features in action. We think it’s pretty powerful stuff, and you’ve told us that you do, too.

In order to provide you with that power, and enable Kendo UI Mobile to be your mobile web and hybrid development tool of choice, two requirements must be met. These are essentially the yardstick by which we measure the capability of a platform to be targeted by Kendo UI Mobile:

Requirement #1. The mobile browser for a target platform must provide support for modern web features on which Kendo UI Mobile depends.

By “modern web features,” I mean things like touch events, CSS Flexbox, CSS Transitions, CSS Animations, and more. Kendo UI Mobile relies on all of these features. Without them, it’s not feasible for us to support a given platform.

Requirement #2. A given widget or UX pattern should exist in some form across all supported platforms.

This requirement allows you to write the same markup and code, and know that things will consistently work, as-expected, on iOS, Android, Windows Phone, and others. For instance, every mobile platform has some concept of a ListView, so we deliver a ListView widget with Kendo UI Mobile that reliably adapts across platforms.

At a high level, this is the framework that we use to assess not just if and when we can support a mobile platform, but also exactly what platform support looks like.

With that covered, let’s talk Windows Phone 8 and Kendo UI Mobile.

Windows Phone 8 and IE10

We know that many of you have been clamoring for Windows Phone support for a while now, and trust me when I tell you that we’ve been wanting to provide it for as long as you’ve been asking! As Todd detailed in a blog post from February of 2012 the real blocker for Windows Phone support on Kendo UI Mobile has been the Windows Phone Browser. In short, Windows Phone 7.x never shipped a browser that met Requirement #1 above. This means that Kendo UI Mobile could not support WP7, no matter how much we wanted to.

Thankfully, Windows Phone 8 ships IE10 as its device browser, and IE10 supports everything you need in a browser in order to deliver a great experience to your customers, with the help of Kendo UI Mobile. Now that Windows Phone 8 is out in the wild, we’re happy to be able to provide support via Kendo UI Mobile widgets and a Windows Phone 8 theme.

It’s important to note here, however, that the latest version of Windows Phone 7x, version 7.8, still ships IE9 as it’s platform browser. Because of this, Kendo UI Mobile is not supported on any version of Windows Phone prior to 8 (7.8, 7.5 or 7).

Kendo UI Mobile and Windows Phone 8

With Kendo UI Mobile, you can now build web apps using HTML, JavaScript and CSS, and deliver an experience that feels like a native Windows Phone 8 app to your users. In addition to creating a theme that adheres to common platform styles and conventions, Kendo UI Mobile widgets like the NavBar, ListView, TabStrip and Switch will work, out-of-the-box, using the same markup and JavaScript you’re already writing to target iOS, Android and Blackberry devices. You can check out demos for all of these widgets at demos.kendoui.com. [Note: Tomorrow, we’ll update these demos to include Windows Phone 8 widgets and examples.]

The widgets we provide, out of the box, in Kendo UI Mobile will help you deliver great Windows Phone 8 web and hybrid apps that also look great on other platforms, as you can see in the screenshot above. That said, our Q1 support for Microsoft’s platform does not include some of the more unique “Windows UI Style” UX paradigms. For instance, we’re not shipping a Panorama mobile control, today. Because there’s no equivalent control for the other supported platforms, using this control would require developers to create platform-specific markup and code, something that runs contrary to why Kendo UI Mobile exists, in the first place. If, on the other hand, you’re looking to specifically target Windows Phone 8 in your applications, we highly recommend checking out our RadControls for Windows Phone where we’ve provided a ton of highly-customized “Windows UI Style” widgets for your Windows Phone 8 applications.

What Kendo UI Mobile does provide in the box for Windows Phone 8 looks pretty slick, and we’re confident that it provides everything you need to start targeting Microsoft’s burgeoning mobile platform. Just as with every Kendo UI Mobile platform we support today, you get the benefit of using web technologies to target multiple platforms, while your users get the benefit of a familiar UX that’s consistent with their preferred device.

But don’t take our word for it. Check out the Beta when it drops tomorrow, and let us know what you think!

Spring Keynote Banner

About the Author
(@BrandonSatrom) is Program Manager for Kendo UI and is based in Austin, TX. A unapologetic lover of the web, Brandon loves to talk about HTML, JavaScript, CSS, open source and whatever new shiny tool or technology has distracted him from that other thing he was working on. Brandon loves writing and speaking and loves hanging out with and learning from other passionate developers, both online and in person. He blogs on occasion at UserInExperience.com

HTML5 vs. Native vs. Hybrid. Global developer survey 2013 results are in.

$
0
0

Some of you may recall that in 2012 we ran a survey on “HTML5 hype” as we wanted to make sure our bullish opinions on HTML5 were in-touch with those of the developer community. We liked the insight we gained from that survey so much, as well as the industry response to it, that we decided to do it again. This time more than 5000 developers responded! We got so much feedback from all over the world that from now on we are dubbing this survey “The Global Developer Survey” 
 
Although the survey investigated a number of HTML5-related issues, we were particularly interested in the following:

  1. HTML5 adoption trends. Both geographical breakdown and adoption based on company size  
  2. HTML5 importance to software developers 
  3. Trends evolving in the Native vs. HTML5 debate
  4. Software developer preferences for existing and emerging mobile platforms

The survey findings are quite interesting! If you’d like to see the full results, just download the free PDF from our Kendo UI Global Developer Survey 2013 page. To give you a little taste of the results here are a few points the survey found. We also created a pretty cool infographic consisting of some key findings; see the bottom of the blog post for details. 

  • Fifty percent (50%) of those surveyed developed a variety of apps in 2012 using HTML5, and 9 out of 10 plan to use HTML5 in 2013.
  • Only 15% of the more than 5,000 surveyed would use “Native-only” to target multiple platforms
  • Developers ranked BlackBerry and Apple iOS as the more difficult platforms to work with.

To see the rest of the survey yourself, check-out the complete survey results for all the details and analysis. 
If you would like your opinions to be included in the next edition of the Kendo UI Global Developer Survey, please sign up for Kendo UI monthly newsletter (see survey page) (no spam, we hate it too!) and watch out for the next survey in the second half of 2013.
 
Please share these results with both HTML5 fans and skeptics; it will help bring them together. Finally, let us know what you think about the results in the comments.

HTML5 infographic

 
Sasha
PS
To see our “HTML5 hype” 2012 survey please go to: http://www.kendoui.com/surveys/html5-adoption-survey-2012.aspx

Spring Keynote Banner

About the Author
is a Marketing Director at Telerik and is based in Toronto, Canada. A geek at heart, Sasha works with HTML and JavaScript developers worldwide and loves learning from passionate people. You can follow Sasha on Twitter @k_sasha.

Kendo UI Q1 2013 Beta available now!

$
0
0

Are you ready for more Kendo UI in your browser? With the next major release of Kendo UI just weeks away, it’s time to talk Beta.

The Kendo UI Spring Release (officially “Q1 2013”) is going to deliver a lot of cool enhancements across the entire Kendo UI framework (Web, DataViz, and Mobile), continuing to deliver on Kendo UI’s vision of providing everything you need to build sites and mobile apps with HTML and JavaScript. But I don’t want to spoil the fun today. For all of the details, join us on March 20th. for the full overview and access to the release bits.

For those of you that really want to get hands-on with the next release early, though, we have now shipped a Q1 2013 beta. The beta bits are available from the Kendo UI download page, and they are your chance to get an early technical preview of the next release. If you have any beta feedback, we’d love to hear it in our forums!

Finally, don’t forget to register for the upcoming release keynote. With thousands of developers joining us for each of the last several releases, this is an online event that’s not to be missed! What’s more, if learning about the newness in Kendo UI is not enough incentive to join, we’ll be raffling some real cool prizes that will change your mind, including a MacBook Air, a couple of Mobile device packs, Nexus 10 tablets and Kendo UI Complete licenses. All you have to do for your shot at winning is register now and join us live on March 20th at 11 AM Eastern!

So, to quickly recap:

Enjoy your week, playing with the Kendo UI beta bits!

Spring Keynote Banner

About the Author
(@BrandonSatrom) is Program Manager for Kendo UI and is based in Austin, TX. A unapologetic lover of the web, Brandon loves to talk about HTML, JavaScript, CSS, open source and whatever new shiny tool or technology has distracted him from that other thing he was working on. Brandon loves writing and speaking and loves hanging out with and learning from other passionate developers, both online and in person. He blogs on occasion at UserInExperience.com

Kendo UI at SXSW 2013. Free TechCab rides, Open Web party tickets, and free hotel rooms

$
0
0

We are packing our bags to head to Austin for SXSW Interactive in less than two weeks, and we can’t wait! In years past, we've set up a booth in the expo center, but this year, we opted to do something more fun and above all, useful for SXSW attendees. For those of you unable to attend, fear not, because we’re going to do our best to bring the best of SXSW to you!

So, what’s Kendo UI team cookin’ up for 2013?

First, we are giving out free cab rides in exchange for your tech ‘confessions’. Yes, that’s right. If you need a ride, just tweet us your location, include the hashtag #SXSWTechCab and our driver will tweet back if she can come pick you up. Just make sure you brush up on your tech-trivia and/or good IT stories! At the end of each day you’ll be able to view our patrons’ thoughts at www.kendoui.com/SXSW.

BTW – you can also submit questions for our TechCabbie to ask of passengers. Simply email us at events@telerik.com, and if your question is the best, you could win a free hotel room at the Aloft Austin at The Domain from March 9 – 13, courtesy of Kendo UI. Winners will be contacted via email and names posted at our Facebook page on March 4.

Second, we are sponsoring the very exclusive Open Web Pool Party (http://openwebsxsw.com), put on by Austin JavaScript (http://austinjavascript.com/). As sponsors, we have a few tickets to give away – did we mention that this will be a hard ticket to come by? Last year we had a blast at this same party with the likes of Brendan Eich, Paul Irish, Chris Wilson and more. If you want to come party with the biggest names of modern Web, including members of the Kendo UI team, just tweet us (@Kendo UI). Include your favorite Kendo UI feature, and we’ll enter you into the drawing. (i.e. My fave @Kendo UI feature is the grid).

In summary:

  1. If you want to participate in TechCab confessions question to us at events@telerik.com. If your question is great, it will be used during our interviews. If your question is the best, you could win a free stay at Aloft hotel!”
  2. If you’d like a free ride while at SXSW, tweet us your location and pick up time using #SXSWTechCab
  3. If you’d like to party like a superstar, tweet your favorite Kendo UI feature to @Kendo UI. (winners announced on March 9 at Kendo UI Facebook page)

This is who you will see at SXSW representing Kendo UI. If you see any one of us, please say hi. We may even have a Kendo UI t-shirt for ya’! J


Brandon Satrom (@BrandonSatrom) is Program Manager for Kendo UI and is based in Austin, TX. A unapologetic lover of the web, Brandon loves to talk about HTML, JavaScript, CSS, open source and whatever new shiny tool or technology has distracted him from that other thing he was working on. Brandon loves writing and speaking and loves hanging out with and learning from other passionate developers, both online and in person. He blogs on occasion at UserInExperience.com

Sasha Krsmanovic

Sasha Krsmanovic is a Marketing Director at Telerik and is based in Toronto, Canada. A geek at heart, Sasha works with HTML and JavaScript developers worldwide and loves learning from passionate people. You can follow Sasha on Twitter @k_sasha.

Irina Slutsky

Irina Slutsky has been asking people questions about technology for many years. This will be the 5th year that she is doing SXSW TechCab Confessions, giving attendees a ride in exchange for their video confession of a technological sin. 

Gerard Juarez

Recently acquired by Telerik, Gerard is a PrEdaTor (read Producer/Editor/Director) and graduate of Vancouver Film School with extensive experience in all aspects of production from cinematography to design and compositing.



Spring Keynote Banner

About the Author
is a Marketing Director at Telerik and is based in Toronto, Canada. A geek at heart, Sasha works with HTML and JavaScript developers worldwide and loves learning from passionate people. You can follow Sasha on Twitter @k_sasha.

Handling CRUD With The Kendo UI JSP Wrappers

$
0
0

This article is going to wrap up what you need to know to get started with the JSP Wrappers for Kendo UI. Let's do just a quick review.

Part 1 (Read It)

  • Created a basic JSP Dynamic Web Application
  • Added a data access layer
  • Created the first servlet
  • Used the Kendo UI TreeView to lazy load hierarchical data

Part 2 (Read It)

  • Expanded the data access layer to include products with relationships to the categories and suppliers tables
  • Wired up a Kendo UI Grid to the products table
  • Implemented server side paging for wicked fast presentation of large data sets
  • Used the "popup" edit mode to improve the editing interface

Part 3 (Read It)

  • Refactored the Java a bit to use some inheritance which reduces the amount of code that I have to duplicate
  • Enabled editing in the Kendo UI Grid
  • Used custom editors to display heterogeneous data

In this final installment, I'm going to be adding in all of the necessary actions to allow users to edit, create, and delete items from my grid. This article builds heavily on the first three, so if you find yourself late to the conversation, might I suggest giving the prior entries a quick read.

Persisting editing changes

The popup editor that we have now is really nice. It's got plenty of real-estate, and all of the forms controls are laid out cleanly so we don't have to fight with CSS or tables.

jsp4_1

You might also enjoy the kitty in the upper right-hand side of that screenshot. I know I do. That's because I have Chrome profiles setup. You can set them up yourself and get your very own kitty.

However if you click the Update button, nothing happens. This is due to the fact that the grid currently has no idea what we want it to do when this button is clicked. What it's going to be looking for is a defined update transport on the data source.

...<kendo:dataSource serverPaging="true" pageSize="10"><kendo:dataSource-transport><kendo:dataSource-transport-read url="api/products">
</kendo:dataSource-transport-read><kendo:dataSource-transport-update url="api/products?update" type="POST">
</kendo:dataSource-transport-update>
...          

 

We need to stop a minute and talk about the update transport settings, because there is actually some pretty important stuff buried in there.

Transports

The transports are broken out into their own elements so that I can provide extra attributes. In the case of the update, it's the type attribute. I am going to be calling the same URL that I did for the read to do the update. In fact, I'm going to be calling that same url for create and delete eventually. How does this work?

The type attribute here specifies that when the servlet responds to this request, it should be using the doPost method as we have specified that this is a POST and not a GET (GET is the default). Additionally, any parameters that we send will go in the body of the request, not the query string. Don’t worry, Kendo UI is going to handle all of this for you. The only thing we need to do is tell the doPost what sort of action we want to do. This is why I am passing update on end of the query string. I can still read the query string in the servlet, we just can't parse parameters off if it as easily as I did in the doGet.

I realize that might be a bit confusing if you are new to HTTP requests and the way that they are made. Don't worry thought, its actually very simple. You can essentially make 4 types of requests from a browser. You can do a GET, POST, PUT, or DELETE. If you are using a framework like Spring MVC, you can use the PUT for a create and the DELETE for a delete. However, plain servlets do not provide a way to do this very easily. It's going to be better for me to stick with a POST and just determine my action from the query string.

Now clicking the button will execute a request to the server.

jsp4_2

 

I just need to tell the server what to do when it receives this request.

Implement the doPost method

Open the Products servlet. If you don't already have a doPost method, add one.

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  // handle CRUD operations here
}

 

Inside of this doPost method, we are going to get the variables from the body of the request and map them into a Products model object. Doing this helps us validate that the data we are getting from the client actually maps to a product object. It's highly advisable that you do server-side data validation in this method as well. We're going to implement it on the client in a just a bit, but always validate your data on both the client and the server.

I created a private method in the servlet which just maps the request parameters into a Product model object.

private models.Product parseRequest(HttpServletRequest request) {

  models.Product product = new models.Product();

  // VALIDATION SHOULD BE DONE HERE AS WELL

  // parse the rest of the information off of the request
  product.setSupplier(new models.Supplier(Integer.parseInt(request.getParameter("Supplier[SupplierID]")), 
      request.getParameter("Supplier[SupplierName]")));
  product.setCategory(new models.Category(Integer.parseInt(request.getParameter("Category[CategoryID]")), 
      request.getParameter("Category[Categoryname]")));
  product.setUnitPrice(Float.parseFloat(request.getParameter("UnitPrice")));
  product.setUnitsInStock(Integer.parseInt(request.getParameter("UnitsInStock")));
  product.setDiscontinued(Boolean.parseBoolean(request.getParameter("Discontinued")));
  product.setProductName(request.getParameter("ProductName"));

  return product;
}

 

It's pretty easy to just read parameters from the request that Kendo UI sends using the servlet getParameter method. How do I know what these parameters are? Simply look at the request in your browser tools. The screenshot above clearly shows me what parameters I am dealing with.

You need to be very comfortable using your browser development tools when doing HTML5 development, or you will be flying blind. If you are on Windows, you can use Fiddler, which will make working with AJAX requests an absolutely sublime experience.

Update repository method

Of course, I also need methods in the data access layer (something that I've called "repositories"). I'm going to implement the update method. While I'm at it, I'm also going to implement create and delete methods, because I'll be needing those very soon.

// update products method
public models.Product doUpdateProduct(models.Product product) throws Exception {

  // create a prepared statement object
  PreparedStatement stmt = null;

  try {

    // build the sql needed for the update
    String sql = "UPDATE Products SET SupplierID = ?, CategoryID = ?, ProductName = ?, " +
           "UnitPrice = ?, UnitsInStock = ?, Discontinued = ? " +
           "WHERE ProductID = ?";

    // prepare the statement for safe execution
    stmt = super.connection.prepareStatement(sql);

    // map the parameters into the query
    stmt.setInt(1, product.getSupplier().getSupplierID());
    stmt.setInt(2, product.getCategory().getCategoryID());
    stmt.setString(3, product.getProductName());
    stmt.setFloat(4, product.getUnitPrice());
    stmt.setInt(5, product.getUnitsInStock());
    stmt.setBoolean(6, product.getDiscontinued());
    stmt.setInt(7, product.getProductID());

    // execute the update
    stmt.executeUpdate();
  }
  catch (Exception e) {
    e.printStackTrace();
    throw new Exception(e.getMessage());
  }
  finally {
    // close all necessary connection related instances
    stmt.close();
  }

  return product;
}

 

The create method has a bit of a twist to it in that what I need back is the id of the item that was just generated. In order to get that, I have to first tell the prepared statement that I'm going to be wanting it, then I have to ask for it after the statement is executed.

// product create method
public int doCreateProduct(models.Product product) throws Exception {

  // set a default id value
  int id = 0;

  //create prepared statement and result set objects
  PreparedStatement stmt = null;
  ResultSet rs = null;

  try {

    // build the sql string
    String sql = &quot;INSERT INTO Products (SupplierID, CategoryID, &quot; +&quot;ProductName, UnitPrice, UnitsInStock, Discontinued ) &quot; +&quot;VALUES (?, ?, ?, ?, ?, ?)&quot;;

    // prepare the statement for safe execution, specifying that we
    // want the auto-generated id from the database returned.
    stmt = super.connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);

    // map the product object to the sql
    stmt.setInt(1, product.getSupplier().getSupplierID());
    stmt.setInt(2, product.getCategory().getCategoryID());
    stmt.setString(3, product.getProductName());
    stmt.setFloat(4, product.getUnitPrice());
    stmt.setInt(5, product.getUnitsInStock());
    stmt.setBoolean(6, product.getDiscontinued());

    // execute the create statement
    int rows = stmt.executeUpdate();
    // if no rows were returned, it failed
    if (rows == 0) {
      throw new SQLException(&quot;Unable to create product&quot;);
    }

    // get the generated key for this item
    rs = stmt.getGeneratedKeys();

    // pull the key off the result set
    if (rs.next()) {
      id = rs.getInt(1);
    }
    else {
      throw new SQLException(&quot;Unable to create product. No auto-genereated key obtained&quot;);
    }
  }
  finally {
    // close all connection related instances
    stmt.close();
    rs.close();
  }

  // return the id that was or wasn&#039;t created
  return id;
}

 

The delete is nice and simple. There is nothing to return from this method. It either worked or it didn't.

// the delete method
public void doDeleteProduct(int productId) throws SQLException {

  // create a prepared statement object
  PreparedStatement stmt = null;

  try {

    // build the simple sql statement
    String sql = "DELETE FROM Products WHERE ProductID = ?";

    // prepare the statement for safe execution
    stmt = super.connection.prepareStatement(sql);

    // set the id of the product to delete
    stmt.setInt(1, productId);

    // execute the delete
    stmt.executeUpdate();
  }
  finally {
    // close all connection related instances
    stmt.close();
  }
}

 

These methods are verbose and there is no doubt about that. Building an entire application this way might result is some carpel tunnel. That's why developers usually choose a framework which handles so much of this manual labor for them. To avoid getting bogged down in the specifics of some specific framework that might not be applicable to everyone, I'm doing things the hard way.

Calling the edit method from the servlet

I've got all the CRUD statements I need in the data access layer, and that's great because calling them from the servlet is nice and easy. At this time I just have to handle the edit.

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

  try {

    // set the content type we are sending back as JSON
    response.setContentType("application/json");

      // get the product id off of the request. only a delete or
      // update will contain the product id
      int productId = request.getParameter("ProductID") == "" ? 0 : Integer.parseInt(request.getParameter("ProductID"));

      // get the type of operation off the query string
      String type = request.getQueryString().trim();

      // parse the rest of the request into a product object
      models.Product product = parseRequest(request);

      // if the query string specified an update
      if (type.equals("update")) {
        // add the product id onto the model and update the product
        product.setProductID(productId);
        product = _repository.doUpdateProduct(product);

        response.getWriter().print(_gson.toJson(product));
    } 
  }
  catch (Exception e) {
    e.printStackTrace();
    // if something went wrong, send back a server error
    response.sendError(500);
  }

}

 

Edits in the grid will now be persisted in the database. The editor sends the product and it's updated properties over to the database. It only does this if a value is actually changed. If you bring up the edit window and don't change anything, it's smart enough to know that and not issue an unnecessary update to the server.

Validation with Kendo UI

There are some fields that I want to validate. I don't want people to be able to completely null out the product name. Right now, they can do that. Kendo UI will do this for me, but I first need to define my constraints in the model of the grid datasource. Once I specify the validation rules in the model, Kendo UI will not let the CRUD actions happen unless these validation rules are met.

....<kendo:dataSource-schema-model id="ProductID"><kendo:dataSource-schema-model-fields><kendo:dataSource-schema-model-field name="ProductName"><kendo:dataSource-schema-model-field-validation required="true"/></kendo:dataSource-schema-model-field><kendo:dataSource-schema-model-field name="Supplier"></kendo:dataSource-schema-model-field><kendo:dataSource-schema-model-field name="Category"></kendo:dataSource-schema-model-field><kendo:dataSource-schema-model-field name="UnitPrice" type="number"></kendo:dataSource-schema-model-field><kendo:dataSource-schema-model-field name="UnitsInStock" type="number"></kendo:dataSource-schema-model-field><kendo:dataSource-schema-model-field name="Discontinued" type="boolean"></kendo:dataSource-schema-model-field></kendo:dataSource-schema-model-fields></kendo:dataSource-schema-model>
....

 

A Kendo UI model is very similar to a server-side model class. It wants to know which field is the id, or primary key. Then I specify each of the fields in the model, and which type they are if they are something other than a standard string. For the ProductName, I specify that this field is required.

Now If I try and submit a row in edit mode with a blanked out product name, it will give me a message which kindly informs me that this is not allowed.

JSP4_3

Kendo UI provides very granular control over validation. I encourage you to read through the documentation on the validation for models. It's a tutorial in and of itself, but they are rather easy to implement and customize once you know how a basic validation rule works in a model. Now you do!

Create and delete

I need to add in definitions for the transport on the datasource on how to handle a create and a delete. Kendo UI refers to a delete as a destroy because delete is a reserved word in JavaScript.

....<kendo:dataSource-transport><kendo:dataSource-transport-read url="api/products"></kendo:dataSource-transport-read><kendo:dataSource-transport-create url="api/products?create" type="POST"></kendo:dataSource-transport-create><kendo:dataSource-transport-update url="api/products?update" type="POST"></kendo:dataSource-transport-update><kendo:dataSource-transport-destroy url="api/products?delete" type="POST"></kendo:dataSource-transport-destroy></kendo:dataSource-transport>
....

 

Let's round this out by adding in the necessary UI for the delete and create actions.

The delete

The delete button is already there next to the edit button. Nothing else is required of me at this point for a delete.

The create

For creating a product, I want to add a toolbar at the top of the grid with a convenient "create" button which opens the popup window.

.....<kendo:grid-editable mode="popup"/><kendo:grid-toolbar><kendo:grid-toolbarItem name="create" /></kendo:grid-toolbar><kendo:dataSource serverPaging="true" pageSize="10">
......

 

That small configuration change to the markup will do the trick. Kendo UI will take care of the rest.

I do need to tell the model what values it should use for the Category and Supplier, because as you will recall, these are not simply fields but actually objects consisting of both a name and an id. I can use Java for that by opening a tag and creating a new supplier and category model object for the default value.

<kendo:dataSource-schema-model id="ProductID"><kendo:dataSource-schema-model-fields><kendo:dataSource-schema-model-field name="ProductName"><kendo:dataSource-schema-model-field-validation required="true"/></kendo:dataSource-schema-model-field><kendo:dataSource-schema-model-field name="Supplier" defaultValue="<%= new Supplier() %>"></kendo:dataSource-schema-model-field><kendo:dataSource-schema-model-field name="Category" defaultValue="<%= new Category() %>"></kendo:dataSource-schema-model-field><kendo:dataSource-schema-model-field name="UnitPrice" type="number"></kendo:dataSource-schema-model-field><kendo:dataSource-schema-model-field name="UnitsInStock" type="number"></kendo:dataSource-schema-model-field><kendo:dataSource-schema-model-field name="Discontinued" type="boolean"></kendo:dataSource-schema-model-field></kendo:dataSource-schema-model-fields></kendo:dataSource-schema-model>

 

Handling create and delete on the server

I've already implemented the create and delete methods in the data access layer, so all that's left to do is call them in the event that I request one of those actions in the query string. The completed doPost method looks like this:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

  try {

    // set the content type we are sending back as JSON
    response.setContentType("application/json");

      int productId = request.getParameter("ProductID") == "" ? 0 : Integer.parseInt(request.getParameter("ProductID"));

      // get the type of operation
      String type = request.getQueryString().trim();

      // parse the rest of the request into an employee object
      models.Product product = parseRequest(request);

      if (type.equals("update")) {
        // add the product id onto the model and update the product
        product.setProductID(productId);
        product = _repository.doUpdateProduct(product);

        response.getWriter().print(_gson.toJson(product));
      }
      if (type.equals("create")) {
        //create the product
        productId = _repository.doCreateProduct(product);
        response.getWriter().print(_gson.toJson(productId));
      }
      if (type.equals("delete")) {
        // delete the product
        System.out.println(type);
        _repository.doDeleteProduct(productId);
      }

  }
  catch (Exception e) {
    e.printStackTrace();
    response.sendError(500);
  }

}

 

Get the completed source code

Grab the completed project for this final tutorial from the GitHub repo. It contains everything that has been covered so far.

And you're done!

That's all there is to it. You have a complete editing interface that you can now begin to customize to your hearts content. If you made it through all 4 of these tutorials, you have already examined some of the most complex scenarios you will likely encounter, and you are ready to go forth and unleash your inner HTML5 creativity.

Kendo UI doesn't build your application for you. Instead, it simply helps you to realize your full potential as a web and mobile developer by taking care of the details that can take the fun out of programming.  This is what allows you to concentrate on bringing your ideas and requirements to life as only you can.

Be sure to sign up for the launch webinar for the JSP Wrappers and MANY other new things in Kendo UI. It's just around the corner and you don't want to miss it. Besides, you stand a chance at winning some pretty awesome prizes and we love to give them out! 

Spring Keynote Banner

About the Author
is a web developer living in Nashville, TN. He enjoys working with and meeting developers who are building mobile apps with jQuery / HTML5 and loves to hack on social API's. Burke works for Telerik as a Developer Evangelist focusing on Kendo UI. Burke is @burkeholland on Twitter.

Exporting the Kendo UI Grid Data to Excel

$
0
0

On my current project, I have been asked to provide the users with the ability to export the contents of any grid to Excel. To do this, I decided to use the XML SDK 2.0 for Microsoft Office to create the Excel spreadsheet. I’ve used the XML SDK 2.0 for Microsoft Office plenty of times for generating Word documents, but this was my first time using it to generate Excel spreadsheets. I found a great article by Mike Wendelius called Creating basic Excel workbook with Open XML that provided what I needed to get started with the XML SDK 2.0 for Microsoft Office.

Since I needed to do provide the ability to Export to Excel for any grid, I decided to create a generic REST end point that would receive any data from any grid and generate the Excel Spreadsheet. Fortunately this is possible to do since JSON.NET supports deserializing JSON data into the dynamic data type.

I am using the Grid widget in Kendo UI Web and didn’t want to have to write code for each grid to handle sending the data to a REST end point to create the Excel spreadsheet and then download the Excel spreadsheet. The Kendo UI framework supports inheritance. I was able to derive from the Grid widget to create a new widget called ExcelGrid. Once I created the ExcelGrid, all I had to do was switch the initialization of all my grids from kendoGrid to kendoExcelGrid.

Getting Started

To get started, you will need to do the following:

  1. Download and install XML SDK 2.0 for Microsoft Office
  2. Read the article by called Creating basic Excel workbook with Open XML
  3. Install Visual Studio 2012

Modifying Excel.cs

First, I needed to make a few changes to Mike Wendelius' Excel.cs. I wanted to leave his code alone, so I changed his Excel class to be a partial class and added a new Excel partial class to the end of the Excel.cs code file. Since I wanted to create the spreadsheet in memory, I added a new CreateWorkbook method that takes a Stream as the parameter. I also wanted to add some additional styles for the column headers, so I added an AddAdditionalStyles method. Here is the code:

public static partial class Excel
{
    /// <summary>
    /// Creates the workbook in memory.
    /// </summary>
    /// <returns>Spreadsheet created</returns>
    public static DocumentFormat.OpenXml.Packaging.SpreadsheetDocument CreateWorkbook(Stream stream)
    {
        DocumentFormat.OpenXml.Packaging.SpreadsheetDocument spreadSheet = null;
        DocumentFormat.OpenXml.Packaging.SharedStringTablePart sharedStringTablePart;
        DocumentFormat.OpenXml.Packaging.WorkbookStylesPart workbookStylesPart;

        // Create the Excel workbook
        spreadSheet = DocumentFormat.OpenXml.Packaging.SpreadsheetDocument.Create(stream, DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook, false);

        // Create the parts and the corresponding objects

        // Workbook
        spreadSheet.AddWorkbookPart();
        spreadSheet.WorkbookPart.Workbook = new DocumentFormat.OpenXml.Spreadsheet.Workbook();
        spreadSheet.WorkbookPart.Workbook.Save();

        // Shared string table
        sharedStringTablePart = spreadSheet.WorkbookPart.AddNewPart<DocumentFormat.OpenXml.Packaging.SharedStringTablePart>();
        sharedStringTablePart.SharedStringTable = new DocumentFormat.OpenXml.Spreadsheet.SharedStringTable();
        sharedStringTablePart.SharedStringTable.Save();

        // Sheets collection
        spreadSheet.WorkbookPart.Workbook.Sheets = new DocumentFormat.OpenXml.Spreadsheet.Sheets();
        spreadSheet.WorkbookPart.Workbook.Save();

        // Stylesheet
        workbookStylesPart = spreadSheet.WorkbookPart.AddNewPart<DocumentFormat.OpenXml.Packaging.WorkbookStylesPart>();
        workbookStylesPart.Stylesheet = new DocumentFormat.OpenXml.Spreadsheet.Stylesheet();
        workbookStylesPart.Stylesheet.Save();

        return spreadSheet;
    }

    /// <summary>
    /// Adds additional styles to the workbook
    /// </summary>
    /// <param name="spreadsheet">Spreadsheet to use</param>
    /// <returns>True if succesful</returns>
    public static bool AddAdditionalStyles(DocumentFormat.OpenXml.Packaging.SpreadsheetDocument spreadsheet)
    {
        DocumentFormat.OpenXml.Spreadsheet.Stylesheet stylesheet = spreadsheet.WorkbookPart.WorkbookStylesPart.Stylesheet;

        // Additional Font for Column Heder.
        stylesheet.GetFirstChild<DocumentFormat.OpenXml.Spreadsheet.Fonts>().InsertAt<DocumentFormat.OpenXml.Spreadsheet.Font>(
            new DocumentFormat.OpenXml.Spreadsheet.Font()
            {
                FontSize = new DocumentFormat.OpenXml.Spreadsheet.FontSize()
                {
                    Val = 12
                },
                FontName = new DocumentFormat.OpenXml.Spreadsheet.FontName()
                {
                    Val = "Calibri"
                },
                Bold = new DocumentFormat.OpenXml.Spreadsheet.Bold()
                {
                    Val = true
                }
            }, 1);

        // Additional Fill for Column Header.
        stylesheet.GetFirstChild<DocumentFormat.OpenXml.Spreadsheet.Fills>().InsertAt<DocumentFormat.OpenXml.Spreadsheet.Fill>(
            new DocumentFormat.OpenXml.Spreadsheet.Fill()
            {
                PatternFill = new DocumentFormat.OpenXml.Spreadsheet.PatternFill()
                {
                    PatternType = new DocumentFormat.OpenXml.EnumValue<DocumentFormat.OpenXml.Spreadsheet.PatternValues>()
                    {
                        Value = DocumentFormat.OpenXml.Spreadsheet.PatternValues.Solid
                    },
                    BackgroundColor = new DocumentFormat.OpenXml.Spreadsheet.BackgroundColor
                    {
                        Indexed = 64U
                    },
                    ForegroundColor = new DocumentFormat.OpenXml.Spreadsheet.ForegroundColor
                    {
                        Rgb = "F2F2F2"
                    }
                }
            }, 2);

        // Column Header
        stylesheet.GetFirstChild<DocumentFormat.OpenXml.Spreadsheet.CellFormats>().InsertAt<DocumentFormat.OpenXml.Spreadsheet.CellFormat>(
            new DocumentFormat.OpenXml.Spreadsheet.CellFormat()
            {
                FormatId = 0,
                NumberFormatId = 0,
                FontId = 1,
                FillId = 2,
                ApplyFill = true,
                ApplyFont = true
            }, 4);

        stylesheet.Save();

        return true;
    }
}

 

Modifying the HomeController.cs

The process of exporting to Excel required 2 calls to the server. The first call creates the Excel spreadsheet, and the second call downloads the Excel spreadsheet. In the HomeController I added 2 Controller Actions, ExportToExcel and GetExcelFile.

ExportToExcel

The ExportToExcel Action Method takes 3 parameters:

  1. model - contains the column definitions
  2. data - data from the grid
  3. title - title for the Spreadsheet

In ExportToExcel I created a MemoryStream and call Excel.CreateWorkbook to create the workbook in memory. I them called the methods needed to add the basic styles and additional styles for the column headers and then I add the worksheet. Using JSON.NET, I converted the model and data parameters to dynamic objects. For each of the columns passed in as the model parameter, I created the columns and set the column width for each column in the spreadsheet. Next I add all the data to the spreadsheet. Finally, I store the spreadsheet in Session to be retrieved. Here is the code:

/// <summary>
/// Create the Excel spreadsheet.
/// </summary>
/// <param name="model">Definition of the columns for the spreadsheet.</param>
/// <param name="data">Grid data.</param>
/// <param name="title">Title of the spreadsheet.</param>
/// <returns></returns>
public JsonResult ExportToExcel(string model, string data, string title)
{
    using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
    {
        /* Create the worksheet. */

        SpreadsheetDocument spreadsheet = Excel.CreateWorkbook(stream);
        Excel.AddBasicStyles(spreadsheet);
        Excel.AddAdditionalStyles(spreadsheet);
        Excel.AddWorksheet(spreadsheet, title);
        Worksheet worksheet = spreadsheet.WorkbookPart.WorksheetParts.First().Worksheet;


        /* Get the information needed for the worksheet */

        var modelObject = JsonConvert.DeserializeObject<dynamic>(model);
        var dataObject = JsonConvert.DeserializeObject<dynamic>(data);


        /* Add the column titles to the worksheet. */

        // For each column...
        for (int mdx = 0; mdx < modelObject.Count; mdx++)
        {
            // If the column has a title, use it.  Otherwise, use the field name.
            Excel.SetColumnHeadingValue(spreadsheet, worksheet, Convert.ToUInt32(mdx + 1),
                modelObject[mdx].title == null ? modelObject[mdx].field.ToString() : modelObject[mdx].title.ToString(),
                false, false);

            // Is there are column width defined?
            Excel.SetColumnWidth(worksheet, mdx + 1, modelObject[mdx].width != null
                ? Convert.ToInt32(modelObject[mdx].width.ToString()) / 4
                : 25);
        }


        /* Add the data to the worksheet. */

        // For each row of data...
        for (int idx = 0; idx < dataObject.Count; idx++)
        {
            // For each column...
            for (int mdx = 0; mdx < modelObject.Count; mdx++)
            {
                // Set the field value in the spreadsheet for the current row and column.
                Excel.SetCellValue(spreadsheet, worksheet, Convert.ToUInt32(mdx + 1), Convert.ToUInt32(idx + 2),
                    dataObject[idx][modelObject[mdx].field.ToString()].ToString(),
                    false, false);
            }
        }


        /* Save the worksheet and store it in Session using the spreadsheet title. */

        worksheet.Save();
        spreadsheet.Close();
        byte[] file = stream.ToArray();
        Session[title] = file;
    }

    return Json(new { success = true }, JsonRequestBehavior.AllowGet);
}

 

GetExcelFile

The GetExcelFile takes one parameter, title which is the title of the spreadsheet.

In GetExcelFile, I check session for the spreadsheet. If it exists, I retrieve the spreadsheet from session and then remove it from session. Finally I return the spreadsheet. Here is the code:

/// <summary>
/// Download the spreadsheet.
/// </summary>
/// <param name="title">Title of the spreadsheet.</param>
/// <returns></returns>
public FileResult GetExcelFile(string title)
{
    // Is there a spreadsheet stored in session?
    if (Session[title] != null)
    {
        // Get the spreadsheet from seession.
        byte[] file = Session[title] as byte[];
        string filename = string.Format("{0}.xlsx", title);

        // Remove the spreadsheet from session.
        Session.Remove(title);

        // Return the spreadsheet.
        Response.Buffer = true;
        Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", filename));
        return File(file, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", filename);
    }
    else
    {
        throw new Exception(string.Format("{0} not found", title));
    }
}

 

Creating the ExcelGrid Widget

Deriving from the Grid Widget

When deriving from an existing Kendo UI widget, there a few things that need to be done:

  • Use the extend method to derive from the existing Kendo UI widget.
  • Implement the init function and call the base class init function.
  • implement the options JSON object with the name attribute set to the name of the new widget.
  • "Register" the new widget using the kendo.ui.plugin function.

Here is the ExcelGrid that inherits from the Grid widget, but doesn't implement any of the new functionality yet:

(function($) {
    var kendo = window.kendo;

  // Create the ExcelGrid.
    var ExcelGrid = kendo.ui.Grid.extend({
        init: function (element, options) {
            // Initialize the grid.
            kendo.ui.Grid.fn.init.call(that, element, options);
        },

        options: {
            name: "ExcelGrid"
        }
    });

  // "Register" the new ExcelGrid with kendo.
    kendo.ui.plugin(ExcelGrid);
})(jQuery);

The kendo.ui.plugin function creates a new kendoExcelGrid function to initialize the widget. To use the ExcelGrid, all you have to do is use the kendoExcelGrid function like this:

var _grid = $("#grid").kendoExcelGrid().data("kendoExcelGrid");

 

Adding the Export to Excel Functionality

To add the Export to Excel functionality, I need to pass in a few extra configuration settings to the ExcelGrid. The new settings will be containing within a JSON object that will be called export. Here is the definition of the new export configuration setting:

export: {
  cssClass: // CSS class the defines the image to be displayed in the "Export" toolbar button.
  title: // The title to be given to the Excel spreadsheet
  createUrl: // The url for the REST end point that will create the Excel spreadsheet.
  downloadUrl: // The url for the REST end point to download the Excel spreadsheet.
}

In the init function, I check to see if the export configuration setting has been passed in. If it has, then I create a toolbar button configuration setting for the Export toolbar button. Next I then initialize the grid. Finally I add the click event handler for the export toolbar button that will call a new function called exportToExcel. Here is the code:

init: function (element, options) {
    var that = this;

    if (options.export) {
        // If the exportCssClass is not defined, then set a default image.
        options.export.cssClass = options.export.cssClass || "k-i-expand";

        // Add the export toolbar button.
        options.toolbar = $.merge([
            {
                name: "export",
                template: kendo.format("<a class='k-button k-button-icontext k-grid-export' title='Export to Excel'><div class='{0} k-icon'></div>Export</a>", options.export.cssClass)
            }
        ], options.toolbar || []);
    }

    // Initialize the grid.
    kendo.ui.Grid.fn.init.call(that, element, options);

    // Add an event handler for the Export button.
    $(element).on("click", ".k-grid-export", { sender: that }, function (e) {
        e.data.sender.exportToExcel();
    });
}

The exportToExcel function sends the columns, data and the title for the spreadsheet to the server using the url set in the export.createUrl configuration setting. When the server is finished creating the Excel spreadsheet, the spreadsheet is downloaded using the export.downloadUrl configuration setting. Here is the code:

exportToExcel: function () {
    var that = this;

    // Define the data to be sent to the server to create the spreadsheet.
    data = {
        model: JSON.stringify(that.columns),
        data: JSON.stringify(that.dataSource.data().toJSON()),
        title: that.options.export.title
    };

    // Create the spreadsheet.
    $.post(that.options.export.createUrl, data, function () {
        // Download the spreadsheet.
        window.location.replace(kendo.format("{0}?title={1}", 
            that.options.export.downloadUrl, 
            that.options.export.title));
    });
}

 

Implementing the ExcelGrid

To use the ExcelGrid with the export configuration settings, simply pass in the export configuration setting along with all the other configuration settings for the Grid. Here is the code:

_grid = $("#grid").kendoExcelGrid({
    dataSource: {
        data: createRandomData(500),
        pageSize: 10,
        schema: {
            model: {
                fields: {
                    FirstName: { type: "string" },
                    LastName: { type: "string" },
                    City: { type: "string" },
                    Title: { type: "string" },
                    BirthDate: { type: "date" },
                    Age: { type: "number" }
                }
            }
        }
    },
    columns: [
        {
            field: "FirstName",
            title: "First Name",
            width: 100
        },
        {
            field: "LastName",
            title: "Last Name",
            width: 100
        },
        {
            field: "City",
            width: 100
        },
        {
            field: "Title"
        },
        {
            field: "BirthDate",
            title: "Birth Date",
            template: '#= kendo.toString(BirthDate,"MM/dd/yyyy") #'
        },
        {
            field: "Age",
            width: 50
        }
    ],
    export: {
        cssClass: "k-grid-export-image",
        title: "people",
        createUrl: "/Home/ExportToExcel",
        downloadUrl: "/Home/GetExcelFile"
    }
}).data("kendoExcelGrid");

 

Conclusion

Now every grid where I want to be able to export the data to Excel, I change kendoGrid to kendoExcelGrid and pass in the export settings. That's it.

Grab The Code

The complete code from this article can be downloaded from the ASP.NET samples repo on GitHub.

Spring Keynote Banner

About the Author
is currently a Senior Principal Software Engineer with ManTech and a Telerik MVP. He has been developing software since 1995; building client server applications, network management and monitoring systems, web applications, mobile applications, and Windows App Store applications. John is currently leading an effort to modernize a suite of enterprise systems for a government customer. John has a passion for exploring technologies and sharing what he has learned through his website "ASP.NET Wiki" at http://www.aspnetwiki.com and speaking engagements.


Adding And Removing Items In kendo.data.DataSource

$
0
0

In my previous post I walked through the basic steps to use a kendo.data.DataSource to build a very simple "to do" list. That version of the app was mostly read-only, with the exception of being able to mark an item as done. You couldn't, however, add or remove...

Kendo UI at HTML5tx

$
0
0

html5-tx Looking for a chance to spend your Saturday learning from some amazing HTML5 experts, like Christopher Schmitt, Mike Taylor (Opera), Brian Rinaldi (Adobe), our own Burke Holland, and many more? Then you better make your way to Austin, Texas tomorrow, Saturday, February 2nd, because it’s time...

Head first into Kendo UI For Java Developers

$
0
0

Last quarter we announced the beta release of our JSP wrappers for Kendo UI. These wrappers are JSP and while our demos are built on Spring MVC, you can use the wrappers with any JSP page.

They provide a strongly typed experience by adding in a special...

Wrapping A Backbone.Collection In A kendo.data.DataSource

$
0
0

In my first post about learning kendo.data.DataSource , a commenter asked me about the differences between this and a Backbone.Collection. He also wondered if there would be any value in creating an adapter that could turn a Backbone.Collection in to a Kendo UI DataSource.

The value that...

Building a better UI – JSP Wrappers part 2

$
0
0

Last week we dove headfirst into Java, Servlets and the Kendo UI JSP Wrappers. This week we'll expand on that experience and explore the most popular and feature rich control in the Kendo UI arsenal - the venerable Grid.

The Grid widget isn't just an interface for...

PHP and Kendo UI

$
0
0

If you've been following me on Twitter you've probably watched a few of my trials and successes in getting PHP up and running on my computer. It's been fun digging in to something that I haven't used in 13+ years. PHP has certainly changed a lot since...

Custom editing in JSP with the Kendo UI Grid

$
0
0

In the last two weeks we have gone from zero to HTML5 hero with theKendo UI JSP Wrappers . That was corny I know, but lets take a look at what we did in each of the previous two parts... Part 1 (Read it …


Breeze.js And The Kendo UI DataSource

HTML5: 10 Provocative Predictions For The Future

$
0
0

For HTML5 developers and decision makers, the most important technologies right now are HTML, JavaScript, CSS, mobile platforms and devices and evolving HTML platforms (browsers and operating systems). But what does that mean in the real world? It means these 10 things in 2013:  

[Note, this article was originally...

Kendo UI Mobile and Windows Phone 8

$
0
0

In the roadmap update post for Q1 2013, I announced that, among other things, our first release of the year would include Kendo UI Mobile support for Windows Phone 8. With tomorrow’s Q1 Beta, you’ll finally be able to get hands on and start building Kendo...

HTML5 vs. Native vs. Hybrid. Global developer survey 2013 results are in.

$
0
0

Some of you may recall that in 2012 we ran a survey on “HTML5 hype” as we wanted to make sure our bullish opinions on HTML5 were in-touch with those of the developer community. We liked the insight we gained from that survey so much, as …

Kendo UI Q1 2013 Beta available now!

$
0
0

Are you ready for more Kendo UI in your browser? With the next major release of Kendo UI just weeks away, it’s time to talk Beta.

The Kendo UI Spring Release (officially “Q1 2013”) is going to deliver a lot of cool enhancements across the entire Kendo...

Viewing all 181 articles
Browse latest View live