Quantcast
Channel: Syncfusion Blogs
Viewing all 473 articles
Browse latest View live

Configuring Single Sign On (SSO) for Syncfusion Dashboard Applications

$
0
0

Microsoft ADFS (Active Directory Federation Services), which runs on Windows Server OS, provides secured single sign-on access (SSO) to registered applications. With the single-sign on (SSO) concept, a user present within the Active Directory can log in with a single ID and password to all the registered applications.

In this blog article, we are going to discuss how to register Syncfusion Dashboard applications with ADFS running in Microsoft Azure and let each user log in to any of those applications with a unique credential. 

Following are the steps to get the single sign-on ADFS to work:

  1.      Creating an Active Directory (AD).
  2.      Creating users and groups.
  3.      Registering the Dashboard Server Application.
  4.       Registering the Dashboard Designer Application.
  5.       Registering the Dashboard Mobile Application.
  6.       Configuring the AD in Dashboard Server.
  7.       Adding AD users and groups in Dashboard Server.

Creating an Active Directory (AD)

To create an active directory, click Create New Resource on the top-left corner of the portal. Search for Active Azure Directory and create the same with Organization name and Initial domain name details. In this example, we have set Syncfusion Dashboards as the organization name and DemoDashboardDirectory as the initial domain name. 

                

Creating users and groups

Once the Active Azure Directory is created, we need to add users. We can also create groups. Select Active Azure Directory on the left side panel under FAVORITES and go to the Users option. Click New User and enter the detailsname, user name, directory role, etc.to create a new user. In this example, we created two usersUser1 and User2 for demo purposes.

IMPORTANT NOTE: Here, a password will be generated automatically for the corresponding user and can be changed during our first login attempt in the respective portal. Hence, copy the password from here for future reference.

Similarly, to create a group, go to the Groups option, right below Users and click New group. Select the appropriate users for this group. In this example, we created a group named DemoDashboardUsers and included User1 and User2 in it.

                

Registering the Dashboard Server Application

Dashboard Server allows global users to view all published dashboards, based on their permissions. To login and view the dashboards through single-sign on access, we need to register this application and link the users in Azure portal.

To register the Dashboard Server application:

  • Select Active Azure Directory on the left-hand side panel under FAVORITES and go to App registrations.
  • Click New application registration and enter the detailsname, application type, and sign-on URLto register the application. In this illustration, we entered the name as Dashboard Server, the application type as Web app/API, and the sign-on URL as dashboard server application hosted URL.
  • Next, move to Dashboard Server settings and select Properties. Here, App ID URI should have the exact value of Sign-on URL.
  • Once the App ID URI is changed, move to Required permissions available below Properties. Click Add and select Microsoft Graph. Enable its permission accordingly.
  • Once Microsoft Graph is added to the application, select Grant Permissions options.

To learn more about Microsoft Graph, click here.

IMPORTANT NOTES:
1. Keys below Required permissions are to be configured and their values need to be noted for later use in Dashboard Server portal. In this illustration, we set DemoKey, which expires in one year, and noted the value, as well.
2. In Settings, we have the Application ID and Object ID of Dashboard Server, which will be used in Dashboard Server for later purposes, as well.

                

Registering Dashboard Designer Application

Dashboard Designer application helps to design a report from scratch and publish the same in the Dashboard Server for all types of users. So, in-order to publish reports in Dashboard Server, we need to log in to the Dashboard Server from Dashboard Designer, which can also be done using single sign-on. For this, we need to register the Designer application in Azure portal and link Dashboard Server to it.

To register the Dashboard Designer application:

  • Select Active Azure Directory on the left-hand side panel under FAVORITES and go to App registrations.
  • Click New application registration and enter the detailsname, application type, and redirect URIto register the application. In this illustration, we have entered the name as Dashboard Designer, the application type as Native, and redirect URI as dashboard server application hosted URL.
  • Next, move to the Dashboard Designer settings and select Required permissions. Click Add and select Dashboard Server, which was created in the previous topic, and enable its permission accordingly.

IMPORTANT NOTE: In the Settings options, we have the Application ID and Object ID of Dashboard Designer, which will be used in Dashboard Server for a later purpose.

                 

Registering Dashboard Mobile Application

Dashboard Mobile allows global users to view all published dashboards (hosted inside Dashboard Server), based on their permission(s). To log in and view the dashboards through single sign-on access, we need to register this application in Azure portal and link Dashboard Server to it.

To do so, repeat the same steps from registering the dashboard designer application. The only change here would be to register Dashboard Mobile Application under the name Dashboard Mobile instead of Dashboard Designer

IMPORTANT NOTE: In Settings, we have the Application ID and Object ID of Dashboard Mobile, which will be used in Dashboard Server for a later purpose.

Configuring AD in Dashboard Server

Now we are going to add the Azure Directory details inside Syncfusion Dashboard Server to synchronize the application. 

Log in to the Dashboard Server portal and navigate to Settings >> User Directory >> Azure Active Directory. Here, you need to enter the tenant name, Client ID, and Client Secret Code. In our illustration, the tenant name is DemoDashboardDirectory.onmicrosoft.com,obtained from Azure, the Client ID is the Application ID of Dashboard Server, and the Client Secret Code is the DemoKey. To learn more about these, recall the note section under Registering Dashboard Server Application. Now test the connection and, on success message, you can proceed to save the settings.

Then, navigate to Settings>> SSO and enable the SSO check box. Fill in all the fields available, as directed in Dashboard Server:

  • Metadata URI and AuthorityIn the Azure portal, select Azure Active Directory >> App registrations >> Endpoints. Here, copy the text from FEDERATION METADATA DOCUMENT and paste it in the Metadata URI option inside the SSO tab in Dashboard Server. Likewise, copy the text from WS-Federation Sign-On Endpoint and paste it in the Authority option inside the SSO tab in Dashboard Server.
  • Tenant NameHere in our illustration, the tenant name is DemoDashboardDirectory.onmicrosoft.com, which we saw while creating the Azure Active Directory.
  • Designer Client ID and Mobile App Client IDYou can add the Application ID of Dashboard Designer and Dashboard Mobile discussed in the note section of the prior topics.
  • Relying Party IDBy default, Dashboard Server portal URL is defined in this field. 

                

                

Adding AD users and groups in Dashboard Server

To add the users and groups, select User Management in the main page of the Dashboard Server portal. Then, select New User >> Import from Azure AD. Search for the users, select them, and click Import and Activate. Similar to adding groups, switch to the Groups tab on the top and repeat the same process.

                

Finally, we have configured our Dashboard Server, Designer, and Mobile application for single sign-on access. You can now visualize the Microsoft ADFS option enabled at the entry level of the applications for the login process. 

                

Throughout this walkthrough, single sign-on facilitates one user name and one password for each user for all the dashboard applications, keeping the login process simple and secured.    

References

https://docs.microsoft.com/en-us/azure/active-directory/active-directory-identityprotection-graph-getting-started

https://help.syncfusion.com/dashboard-platform/dashboard-server/how-to/set-up-azure-ad

https://help.syncfusion.com/dashboard-platform/dashboard-server/site-settings/azure-active-directory

https://help.syncfusion.com/dashboard-platform/dashboard-server/site-settings/single-sign-on/sso-settings

To learn more about the following technical terms, refer to the corresponding links.

ADFS - https://msdn.microsoft.com/en-us/library/bb897402.aspx

SSO - https://msdn.microsoft.com/en-us/library/aa745042(v=bts.10).aspx


Creating Your Own Icon Font Using Metro Studio

$
0
0

Using high quality images is an effective way to keep users’ attention and build their interest in reading the content of webpages and applications. However, the images should be lightweight for quick responsiveness and look crisp on high resolution displays. The best solution is to use icon fonts instead of images.

Key reasons to use icon fonts 

  • Icons are scalable, without loss of quality in high resolution display.
  • Icons are sharp and crisper.
  • Icons are lightweight and they all can be loaded in a single file.
You can create your own icon font using our Metro Studio application to create a metro project and export it to icon font. This blog post is about to teach you how you can create your own icon font and how to use it in your application.

Creating a metro project

After launching the Metro Studio application, you can find icons with different categories. You can create your metro project by following the below steps:
  1. Select the required icons to create an icon font.
  2. Drag the required icons to the “Drop to create a project” option on bottom left of application.
  3. Name your project.

Creating Metro Project
Now your metro project is ready to create icon fonts.

Creating the icon font

Once you select all the required icons, you can create your icon font with the following steps:
  1. Click the Create Font option in your metro project.
  2. By default, each icon is assigned with Unicode. Before downloading the icon fonts, you can rename the icons and define Unicode character for each. Also, you can reset the Unicode of icons using the option on the bottom left of the dialog window.
  3. Once character mapping is done, you can create your icon font with the Generate Font option on bottom right of dialogue.
  4. Name the icon font and choose the location to which to download the icon font.

Icon Font Generation
Icon fonts generated by Metro Studio have various font formats (to support cross-browser compatibility) and demo files.

Icon Font Files
Generated icon fonts can be used in webpages by mapping the icon fonts in your HTML, CSS, and JavaScript. They can also be used in WPF, UWP, and Xamarin applications. Let’s look at how to use the generated icon fonts in a UWP application.

How to use icon font

Once the font file containing icons is embedded in your application, you can use it in different controls that support font family changes. If you had a UWP project, for instance, you’d follow these steps to embed the font file in your project and use our icons in your control:

  1. Copy the true type font file (ttf file) from the fonts folder to your application location.
  2. Include the font file in your project.
  3. Set the Build Action as “Content” for the font file.

Set Build Action as Content
Once you reference the font file in your project, you can change the Font Family of the control to use icons from our font file. Font Family can be set to the control in the following format.
FontFamily ="[PathToTTF]#[NameOfFontFamily]"
We can define our font family in code behind also, as in the following code samples.
string fontFilePath = "ms-appx:///Gallery.ttf#Gallery";
fontIcon.FontFamily = new FontFamily(fontFilePath);
Use the Unicode or Glyph of corresponding icon as text or content value of the control to display the icon.
<TextBlock Foreground="White" FontFamily = "Gallery.ttf#Gallery" Text="&#xe701;" FontSize="18" /><TextBlock Foreground="White" FontFamily = "Gallery.ttf#Gallery" Text="&#xe701;" FontSize="18" /><TextBlock Foreground="White" FontFamily = "Gallery.ttf#Gallery" Text="&#xe702;" FontSize="18" />
Icon Font Used in UWP Application

Wrapping up

For more information and details about other features, please refer to our documentation, where you will see customized Character mapping and CSS properties.

The sample code showing how to use the icon font in a UWP application can be downloaded at the Icon Font Sample.

You can download the Metro Studio setup here. Feel free to share your feedback in the comments below. You can also contact us through our support forum or Direct-Trac. We are happy to assist you!

Interview with Ionic Succinctly Author Ed Freitas

$
0
0

The following is a short interview with Succinctly author Ed Freitas, whose new book, Ionic Succinctly, was published on Monday, April 23. You can download the book on the Syncfusion website.

 


 

What should people know about the subject of your book? Why is it important?

The landscape of mobile app development frameworks is fragmented. On one side, some platforms attract developers because of their native performance gains, while on the other side, the HTML-based frameworks have always made developers think twice about even choosing them.

Unlike other cross-platform frameworks, Ionic has been consistently gaining popularity and the framework has become the de facto standard in hybrid app development. Following are some convincing features for why people should be interested in this framework, and thus my book:

·      Cross-platform—The Ionic framework lets you use the exact same code base for all supported mobile platforms, eventually saving you a ton of development and maintenance time and giving you cost benefits.

·      Free of cost—Ionic is open source and available under MIT license, which grants permission, free of charge, to any person obtaining a copy of the software, to deal in the software without restriction. In simpler words, you can use Ionic commercially without paying a cent. 

·      Strong ecosystem—Ionic doesn’t come with one compressed file of the framework and make you do the heavy lifting of creating builds, setting up environments, and doing packaging by installing tons of other libraries and tools.

·      Based on Apache Cordova—Apache Cordova is an open-sourced app packaging framework being used by many other frameworks, and Ionic therefore has become one of the standards in hybrid app development. Ionic allows developers to use standard web technologies—HTML5, CSS3, and JavaScript—for cross-platform development.

·      Easy learning curve—Ionic uses HTML, CSS, and JavaScript for Ionic app development and JavaScript is the lingua franca of the web. Millions of developers around the world are working on web apps using the same technology stack.

·      Supports Angular 2+ and Typescript

·      Strong community support

 

When did you first become interested in Ionic?

Approximately a year ago. I was looking for a way to write hybrid apps without using different frameworks for each device platform. I explored various options and Ionic was the one that caught my eye. It was instant love!

 

By writing this e-book, did you learn anything new yourself?

Yes, very much. The whole writing experience was a continuous and fun learning challenge! It was interesting to learn the front-end markup as well as the code-behind using Angular and Typescript. The other great thing about Ionic is that it enforces certain good development practices that allow you to organize your code in a way that makes it easy to make changes much later on.

 

How will Ionic change over the next few years?

It's just exponentially exploding in terms of improvements by the day, with new side projects and frameworks that complement Ionic development, most recently Stencil and Capacitor, also from the makers of the Ionic framework. 

 

Do you see Ionic as part of a larger trend in software development?

It is indeed part of a much larger trend. Ionic was probably the first serious player in hybrid application development along with React Native. However, there are now various other alternatives in the market, such as NativeScript, Monaca, Framework7, and others. The future of this space looks super exciting!

 

What other books or resources on this topic do you recommend?

 

There are a lot of nice books out there that broaden this topic, however, I recommend Mobile App Development with Ionic 2: Cross‑Platform Apps with Ionic, Angular 2, and Cordova by Chris Griffith, published by O'Reilly Media.

Validate and Restrict Connections in a Diagram WPF

$
0
0

Connectors play an important role in a diagram. They visually indicate the relationship between two objects. There are several restrictions you can make when you set a connection, based on the kind of diagram you use. For example, you may want to restrict a flow in a specific direction, or you may not want to connect an object more than once. In this blog, let’s see how to impose such restrictions in diagram. 

I assume that you have some basic knowledge of diagram with nodes, connectors, and ports. This blog is written based on diagram for the WPF platform, but similar functionality is also available in other platforms. If you are new to the diagram component, please refer to the Getting Started section of our help documentation.

If you are trying a logic gate diagram: 

  • Nodes represent the gates.
  • Ports represent the ‘in’ and ‘out’ pins of gates.
  • A connector represents a flow or wire connecting pins.

Default connection behavior

By default, diagram does not enforce any rules, and allows connections anywhere, any number of times: 

  • Connectors can be left disconnected from objects, just by specifying the source and target point.
  • Connectors can be connected between nodes.
  • Connectors can be connected between ports (a specific point on a node or connector).
  • A connector has two ends; each end can take part in any of the above three.

When the cursor is over a valid object to make a connection, you will see following visual effects:

  • A green rectangle indicator on the target object.
  • An animation focusing the target object.
  • The cursor turns into a cross cursor.

When the cursor is over an object that is restricted, a green highlighter will not be visible and animation will not take place.

Restrictions

Restrict to connect to only ports (not to nodes)

If you want to connect only between ports and not between nodes, remove connectable capabilities from NodeContraints and set PortConstraints to all allow connections, as shown in the following.


Restrict connecting to only ports (not to nodes)

Resource

<syncfusion:NodeConstraints x:Key="disableConnect">

Selectable, Draggable, Resizable, Rotatable,InheritPortVisibility

</syncfusion:NodeConstraints>

<syncfusion:PortConstraints x:Key="enableConnect">

InheritPortVisibility, Connectable

</syncfusion:PortConstraints>

Node and Port constraints

<local:NodeVM Shape="{StaticResource AndGate}"

              Constraints="{StaticResource disableConnect}"

              OffsetX="100" OffsetY="100"

              UnitWidth="70" UnitHeight="50">

    <local:NodeVM.Ports>

        <syncfusion:PortCollection>

            <local:PortVM NodeOffsetX="0"

NodeOffsetY="0.2"

Constraints="{StaticResource enableConnect}" />

        </syncfusion:PortCollection>

    </local:NodeVM.Ports>

</local:NodeVM>

<local:NodeVM Shape="{StaticResource AndGate}"

                Constraints="{StaticResource disableConnect}"

                OffsetX="100" OffsetY="100"

                UnitWidth="70" UnitHeight="50">

    <local:NodeVM.Ports>

        <syncfusion:PortCollection>

            <local:PortVM NodeOffsetX="0"

NodeOffsetY="0.2"

Constraints="{StaticResource enableConnect}" />

        </syncfusion:PortCollection>

    </local:NodeVM.Ports>

</local:NodeVM>

Restrict in/out connection

You can validate the direction of the connection by specifying InConnect or OutConnect to PortConstraints as shown in the following.


Restrict in/out connections

Resources

<syncfusion:NodeConstraints x:Key="disableConnect">

Selectable, Draggable, Resizable, Rotatable, InheritPortVisibility

</syncfusion:NodeConstraints>

<syncfusion:PortConstraints x:Key="enableConnect">

InheritPortVisibility, Connectable

</syncfusion:PortConstraints>

<syncfusion:PortConstraints x:Key="enableInConnect">

InheritPortVisibility, InConnect

</syncfusion:PortConstraints>

<syncfusion:PortConstraints x:Key="enableOutConnect">

InheritPortVisibility, OutConnect

</syncfusion:PortConstraints>


Port constraints for in and out connections

<local:NodeVM Shape="{StaticResource AndGate}"

                Constraints="{StaticResource disableConnect}"

                OffsetX="100" OffsetY="100"

                UnitWidth="70" UnitHeight="50">

    <local:NodeVM.Ports>

        <syncfusion:PortCollection>

            <local:PortVM NodeOffsetX="0" NodeOffsetY="0.2"

Constraints="{StaticResource enableInConnect}" />

            <local:PortVM NodeOffsetX="0" NodeOffsetY="0.8"

Constraints="{StaticResource enableInConnect}"/>

            <local:PortVM NodeOffsetX="1" NodeOffsetY="0.5"

Constraints="{StaticResource enableOutConnect}"/>

        </syncfusion:PortCollection>

    </local:NodeVM.Ports>

</local:NodeVM>

Restrict number of connections

You can restrict the number of connections that can be connected to a port by overriding methods as shown in the code example.


Restrict number of connections

public bool CanCreateConnection(IConnector ignore)
{
    var info = this.Info as INodePortInfo;
    if (info.Connectors != null)
    {
        var count = info.Connectors.Where(c => c != ignore).Count();

        // Validate number of connections.
        if (MaxConnection >= 0 && count >= MaxConnection)
        {
            return false;
        }
    }
    else if(MaxConnection == 0)
    {
        return false;
    }
    return true;
}
public class CustomDiagram : SfDiagram
{
    // Validate and choose required tool.
    protected override void SetTool(SetToolArgs args)
    {
        base.SetTool(args);
        if(args.Source is IPort)
        {
            args.Action = ActiveTool.Draw;
        }

        if (args.Source is PortVM && args.Action == ActiveTool.Draw)
        {
            var port = args.Source as PortVM;
            if (!port.CanCreateConnection(null))
            {
                args.Action = ActiveTool.None;
            }
        }
    }

    // Validate the connection when connector endpoints are dragged.
    protected override void ValidateConnection(ConnectionParameter args)
    {
        if(args.TargetPort is PortVM)
        {
            var port = args.TargetPort as PortVM;
            if (!port.CanCreateConnection(args.Connector as IConnector))
            {
                args.TargetPort = null;
            }
        }
        base.ValidateConnection(args);
    }
}

Customizing visual effects

  

Show ports always

To show ports always, irrespective of any of their constraints or mouse-over state, set PortVisibility as Visible.

diagram.PortVisibility = PortVisibility.Visible;

Show ports only on mouse-over

To show ports only mouse is over the node or near the port, set PortVisibility as MouseOver.

diagram.PortVisibility = PortVisibility.MouseOver;

Show only valid ports during connection

Set PortVisibility as ValidConnection to show ports only when the cursor is over a node and only when validation is passed. That is, if a port does not pass the validation, it will stay hidden.

diagram.PortVisibility = PortVisibility.ValidConnection;

Hide animation during connection

You can hide the animation that indicates connection by applying a null template for RunTimeConnectionIndicator.

You can download the sample that demonstrates port validation and visual effects at ConnectionValidation.

Summary

In this post, you can see how connections to ports and nodes can be restricted. Likewise, you can also enforce your business constraints. For example, in a class diagram, you can make the following restrictions:

  • A class object cannot have more than one base class.
  • An interface object should not derive a class object.
  • A struct object cannot have any base struct or class object.

There are many more port options to explore. To explore ports more, please refer to our help documentation on Ports.

If you’re already a Syncfusion user, you can download the product setup here. If you’re not yet a Syncfusion user, you can download a free, 30-day trial here.

If you have any questions or require clarification about these features, please let us know in the comments below. You can also contact us through our support forum or Direct-Trac. We are happy to assist you!

What’s Coming in 2018 Volume 2: Image Editor in Xamarin.Forms

$
0
0

We are excited to share the new features we are including in our upcoming 2018 Volume 2 release for the image editor control in Xamarin.Forms:

  • Custom View / Custom image Annotation
  • Font support for our text annotation
  • Customizing height for toolbar and toolbar item
  • Customizing stroke thickness using slider
  • Customizing opacity for the annotated items
  • New toolbar design

Custom view / Custom image annotation

There were lot of requests for a way to add another image as an annotation over the editing image and yes, we heard you! Now we support this functionality and furthermore we have gone one step ahead and provided support to add a custom view as an annotation so that you can add any UI element over an image as an annotation, say for e.g. you can add our Syncfusion Xamarin.Forms Chart over an image and save it. And obviously by the way you can add any image over an editing image too as a custom view. Following is a code snippet showing how we can add or remove a custom annotation. 

   Image imageView = new Image();

   imageView.Source = ImageSource.FromResource("NamsSpace.ImageName.png");

   imageView.HeightRequest = 300;

   imageView.WidthRequest = 300;

   imageEditor.AddCustomView(imageView);


Adding custom view over an image

Font support for text annotation

Image editor already supports text annotation, but now it supports text annotation with customizable fonts. This feature helps in creating more and more realistic and beautiful image banners with customizable fonts.  The following code snippet shows how you can add your required font to text annotation. 

 TextSettings textSettings = new TextSettings();

 textSettings.FontFamily = "Herculanum";

 imageEditor.AddText("Your Text",textSettings);


Font support for text annotation


Customizing height for toolbar and toolbar item

Everyone loved our support to add and remove any toolbar item from our toolbar in our previous release, now in our upcoming release this feature as an upgrade to customize the height of toolbar and toolbar item. Each toolbar item has an icon and a text, now the height and font size can be customized as like in the code snippet below.


 imageEditor.ToolBarSettings.HeaderToolbarHeight = 40; 

 imageEditor.ToolBarSettings.FooterToolbarHeight = 40;

 imageEditor.ToolBarSettings.SubItemToolbarHeight = 40;

 

 imageEditor.ToolBarSettings.ToolbarItems[0].TextHeight = 20; // Individual Item Text Height

 imageEditor.ToolBarSettings.ToolbarItems[0].IconHeight = 20; // Individual Item Icon Height


Customizing toolbar height


Customizing stroke thickness using slider

Our built-in toolbar has an option to change the stroke thickness for our pen tool using combo box, now we have provided support to change the stroke thickness using slider, which gives more UI flexibility to customize the stroke thickness. We have also extended this support for our shapes as well. 

Customizing opacity for the annotated items

Image editor now supports customizing the opacity for the annotated items like shapes, text, drawing path and custom view. 


Customizing the opacity for annotations

New toolbar design

We have also carefully revamped our Toolbar UI so that it gives more freedom to customize the toolbar as you desire with more UI flexibility. 



New flexible toolbar design

We have demonstrated these new features to show you how handy our image editor control is in developing your customized, feature-rich applications. Syncfusion invites you to try out these features in the upcoming 2018 Volume 2 release, which is expected to roll out at the end of May 2018. You can also download the demo sample with pre-release assemblies from this link. Please feel free to provide your valuable feedback in the comments section below. 

Note: The demo application contains pre-released assemblies



Conversations at Microsoft Build 2018

$
0
0

At Microsoft Build this year, we had great conversations with attendees, customers, partners, exhibitors, and our friends at Microsoft about the latest technology trends and exciting projects.


               

 

At the mobile development area, I met Jim Bennett, Cloud Developer Advocate at Microsoft, with whom I discussed ways drones could be used for good, as demonstrated in the first day keynote. He had many examples, the most compelling of which involved his wife’s family in west Africa. The family grows stevia on its farm, and struggles to keep out unwanted visitors who may steal its cows, or allow their cows to graze on the stevia fields, which would devastate the family’s crops. A drone could be used to patrol the property to look for broken fences or unfamiliar faces,and send an alert to the farmers to check it out. The drone could literally save the family’s livelihood if a problem is caught early.

 

                            

Drone on display at DJI booth. Source: Marissa.

 

Another theme at Build was mixed reality and how it could be used to help medical professionals treat and diagnose patients. Plain Concepts, a Microsoft vendor, showcased how to use mixed reality to train new doctors, EMTs, and other medical professionals.  In the image below, you can see what a cardiologist might see through HoloLens in this augmented reality – a 3-D version of a patient’s heart that is based on one set of scans. With this technology, if the cardiologist wanted to see different angles, they could simply manipulate this 3-D image instead of having to request further scans of the patient and waiting another week for those results.

 

                                

                                         Plain Concepts booth at Build. Source: Marissa.

 

I also had the pleasure of meeting a Syncfusion customer who had worked with our diagram component for many years and loved it. He was interested in starting his own company soon, and appreciated how the Syncfusion Community License gives start-ups enterprise-grade components for free.

 

                 

Syncfusion diagram component.

 

I met another Xamarin MVP who loved our Succinctly series of free e-books, our collection of more than 130 short e-books on a variety of technical topics, spanning web and mobile development, specific programming languages, and everything in between. If you’re not yet familiar with them, browse our library at syncfusion.com/ebooks.

 

Alicia and I enjoyed visiting with David Ortinau of Microsoft and Ed Snider, a Microsoft MVP, who had been to our office a few times to speak at Xamarin Dev Days.  David had created an AI app to recognize logos at Build and had asked us to help train the app by sending him various versions of our logo. We were happy to help.

 

                                     

Left to right: Ed Snider, Microsoft MVP and Marissa Keller Outten of Syncfusion. Source: Marissa  

                    

Left to right: Alicia Morris of Syncfusion, David Ortineau of Microsoft,, and Marissa Keller Outten of Syncfusion. Source: Marissa.

 

Syncfusion exhibited at Microsoft Build as well. Here is the Syncfusion team at our booth right before the expo hall opened:

                           

Syncfusion staffers at Build. Source: Syncfusion.

 

We enjoyed speaking with attendees about their projects and sharing updates on our Xamarin and JavaScript UI toolkits. TypeScript, Angular, and React were the most popular talking points with visitors who were amazed at how much functionality our products offer. One visitor wanted a multiselect component, and was surprised to see we offer one in our Essential JS 2 suite. Other visitors, new to Xamarin.Forms, were impressed by the number of controls we offer—over one hundred—in Essential Studio for Xamarin.

 

Another highlight with many visitors was the ability of our Essential JS 2 data grid to work with hundreds of thousands of rows, even though thousands of Build attendees were using the same Wi-Fi network.


                      

Essential JS 2 Data Grid. Source: Syncfusion.

 

                     

 

Syncfusion staffers talking with attendees. Source: Syncfusion  

Syncfusion staffers getting ready for the attendees. Source: Syncfusion

 

We had a great time attending and exhibiting at Microsoft Build. We reconnected with customers and Microsoft contacts, met with marketing partners, and engaged with attendees. It was a great opportunity to speak with customers and spread the word about our wide range of Xamarin and JavaScript UI components. We look forward to next year!

 

For more information on Microsoft Build or Syncfusion’s offerings, check out these links:

 

·      Microsoft Build content: https://developer.microsoft.com/en-us/events/build/content

·      Microsoft Build keynotes: https://developer.microsoft.com/en-us/events/build/keynotes

·      Syncfusion Essential Studio for JavaScript: https://www.syncfusion.com/products/javascript

·      Syncfusion Essential Studio for Xamarin: https://www.syncfusion.com/products/xamarin

·      SyncfusionSuccinctly series of free e-books: https://www.syncfusion.com/ebooks

Put OpenStreetMap, Bing Maps in Your Xamarin.Forms Application Using Syncfusion Maps

$
0
0

Every release, our Xamarin.Forms suite is maturing with the addition of new controls, and each control is maturing with the addition of features and bug fixes. This would not be possible without your support and feedback.

We are glad to announce that we have provided built-in online map provider support to SfMaps in our 2018 Volume 2 release. You can now show OpenStreetMaps and Bing maps using the Xamarin.Forms maps control, providing the ability to visualize satellite, aerial, street map, or other kinds of imagery tiles without using any external shapes files.

OpenStreetMap

The OpenStreetMap(OSM) is a map of the world built by a community of mappers that is free to use under an open license. It allows you to view geographical data in a collaborative way from anywhere on the Earth. It provides small tile images based on our requests and combines those images into a single one to display the map area in our maps control. 

Maps control uses the imagery layer to display the tile images from the OSM service. To use OSM, you need to add an imagery layer in maps’ Layers collection and set LayerType as “OSM,” as shown in the following code.

<maps:SfMaps><maps:SfMaps.Layers><maps:ImageryLayer LayerType="OSM" ></maps:ImageryLayer></maps:SfMaps.Layers></maps:SfMaps>


Bing maps

Bing maps is a map of the entire world owned by Microsoft. As with OSM, it provides map tile images based on our requests and combines those images into a single one to display a map area. To use Bing maps, you need to set the LayerType as “Bing”. Also, you need to set the Bing maps key (which is obtained from this) to BingMapKey property,  as shown in the following code.

<maps:SfMaps ><maps:SfMaps.Layers><!--Need to create Bing maps key and set to BindMapKey property--><maps:ImageryLayer LayerType="Bing" BingMapKey="" /></maps:SfMaps.Layers></maps:SfMaps>


Maps supports three types of Bing map viewing style options: Aerial, AerialWithLabel, and Road. The default view of Bing map style is Road.

Aerial

Aerial view displays satellite images to highlight roads and major landmarks for easy identification. To apply the Aerial view, you need to set BingMapStyle as “Aerial,” as shown in the following code.

<maps:SfMaps ><maps:SfMaps.Layers><!--Need to create Bing maps key and set to BindMapKey property--><maps:ImageryLayer LayerType="Bing" BingMapKey="" BingMapStyle="Aerial" /></maps:SfMaps.Layers></maps:SfMaps>


AerialWithLabel

AerialWithLabel view displays the Aerial map areas with labels for continent, country, ocean, etc., names. To apply this type of view style, you need to set BingMapStyle as “AerialWithLabel,” as shown in the following code.

<maps:SfMaps ><maps:SfMaps.Layers><!--Need to create Bing maps key and set to BindMapKey property--><maps:ImageryLayer LayerType="Bing" BingMapKey="" BingMapStyle="AerialWithLabel" /></maps:SfMaps.Layers></maps:SfMaps>


Road

Road view displays the default map view of roads, buildings, and geography. To apply the Road view, you need to set BingMapStyle as “Road,” as shown in the following code.

<maps:SfMaps ><maps:SfMaps.Layers><!--Need to create Bing maps key and set to BindMapKey property--><maps:ImageryLayer LayerType="Bing" BingMapKey="" BingMapStyle="Road" /></maps:SfMaps.Layers></maps:SfMaps>


Markers

Maps provides additional options to add custom markers over the OSM maps layer. Just set the corresponding location’s coordinates of latitude and longitude, and you can place the marker with labels. The type of marker can be changed to built-in shapes such as circles, diamonds, rectangles, or squares. Also, custom images can be added as markers to highlight a location.

<maps:SfMaps ><maps:ImageryLayer.Markers><maps:MapMarker  Label="United States" Latitude="38.8833" Longitude= "-77.0167"/><maps:MapMarker Label="Brazil" Latitude="-15.7833" Longitude= "-47.8667" /><maps:MapMarker Label="India" Latitude="21.0000" Longitude= "78.0000" /><maps:MapMarker Label="China" Latitude="35.0000" Longitude= "103.0000" /><maps:MapMarker Label="Indonesia" Latitude="-6.1750" Longitude= "106.8283" /></maps:ImageryLayer.Markers></maps:SfMaps >


Zooming and panning

Maps provides interactive zooming and panning support for OSM and Bing maps.

Zooming helps you get a closer look at a particular area on a map for in-depth analysis. Panning helps you move a map around to focus the target area. You can perform zooming and panning with the pinching gesture in a map area.


We hope you will enjoy this feature that makes Syncfusion maps beautiful and more mature. Be sure to check out the samplewhich is readily runnable, and see just how easy it is to add OSM and Bing maps to your application using map control.

If you have any questions or need clarification, please let us know in the comments section. You can also contact us through our support forum or Direct-TracWe are happy to assist you!

Note: The demo application contains pre-released assemblies

Introducing New Angular Tree View Component in Essential JS 2

$
0
0

The tree view control is used to represent hierarchical data in a tree-like structure, with the option of expanding and collapsing the tree nodes. Tree view has many flexible options, including data binding, node icon support, check boxes, node templates, drag and drop, and node editing supports.

This blog provides an overview of the tree view control from Essential JS 2, and also shows you the basic usage and the features of tree view.

Getting started

We can see how to gets started with the tree view component in the Angular platform through the following simple steps:

  1. First, we can create a basic Angular application through theangular-cli. If you don’t have the CLI tool already, then you can install it globally with the following command.
  2. npm install -g @angular/cli

  3. Create an Angular application using the following command.
  4. ng new treeview-app

    This will create the application and download its dependencies.

  5. Once the application is created, you can install the packages for tree view component into your application by using the following command.
  6. cd treeview-app
    npm install @syncfusion/ej2-ng-navigations --save

    Here, --save will include the navigations package in the dependencies list of package.json.

  7. Now, the environment-related configurations are completed. Next, you can create a component to place the tree view inside. You can use the following command to create a component in your application.
  8. ng generate component home

    After that, the following files will be created.

    CREATE src/app/home/home.component.html (23 bytes)
    CREATE src/app/home/home.component.spec.ts (614 bytes)
    CREATE src/app/home/home.component.ts (261 bytes)
    CREATE src/app/home/home.component.css (0 bytes)
    UPDATE src/app/app.module.ts (388 bytes)

    Then you need to import the tree view component inapp.module.ts, and include it in the declarations.

    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    
    import { AppComponent } from './app.component';
    import { HomeComponent } from './home/home.component';
    
    import { TreeViewComponent } from '@syncfusion/ej2-ng-navigations';
    
    @NgModule({
      declarations: [
        AppComponent,
        HomeComponent,
        TreeViewComponent
      ],
      imports: [
        BrowserModule
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule { }

  9. Essential JS 2 components support a set of built-in themes, and here we will use the Material theme for the tree view. To add the material theme in your application, you need to import material.css in styles.css.
  10. @import '../node_modules/@syncfusion/ej2-ng-navigations/styles/material.css';

  11. We have successfully completed the configurations related to tree view. Now you need to initialize your first tree view component in home.component.html.
  12. <ejs-treeview id="myTree"></ejs-treeview>

    Then add the home component in app.component.html (or where you want to place the tree view).

    <div style="text-align:center"><h1>
        Welcome to the Angular TreeView sample!</h1></div><app-home></app-home>

  13. Finally, run the following command to see the output in a browser.
  14. ng serve --open

    Note: Now tree view is rendered without any nodes, since data binding is essential for this.

Data binding

Undoubtedly, tree view is a data-bound component that will need to be bound with a data source. The data source should be in the form of any valid hierarchical structure such as XML, a nested array of JSON objects, or a self-referential structure.

The tree nodes will be rendered from the dataSource based on the fields property, where the following columns are mandatory to display a tree view:

  • Text - defines the display text of the tree node.
  • Child - defines the child data source to render the sub-nodes (children nodes).

If the data source has different column names, then we should map those names through the fields property.

Now we can construct simple hierarchical data in home.component.ts, and map it to the tree view fields.

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {

  public treeData: Object[] = [
        {
            nodeId: '1', nodeText: 'Documents',
            nodeChild: [
                { nodeId: '11', nodeText: 'Team management.docx' },
                { nodeId: '12', nodeText: 'Entity Framework Core.pdf' },
            ]
        },
        {
            nodeId: '2', nodeText: 'Downloads',
            nodeChild: [
                { nodeId: '21', nodeText: 'Sales report.ppt' },
                { nodeId: '22', nodeText: 'Introduction to Angular.pdf' },
                { nodeId: '23', nodeText: 'Paint.exe' },
                { nodeId: '24', nodeText: 'TypeScript sample.zip' },
            ]
        },
        {
            nodeId: '3', nodeText: 'Music',
            nodeChild: [
                { nodeId: '31', nodeText: 'Crazy tone.mp3' }
            ]
        },
        {
            nodeId: '4', nodeText: 'Videos',
            nodeChild: [
                { nodeId: '41', nodeText: 'Angular tutorials.mp4' },
                { nodeId: '42', nodeText: 'Basics of Programming.mp4' },
            ]
        }
  ];

  public treeFields: Object = { 
    dataSource: this.treeData, 
    id: 'nodeId', 
    text: 'nodeText', 
    child: 'nodeChild' 
  };

  constructor() { }

  ngOnInit() {

  }

}

Initialize the tree view in home.component.html, and assign the fields to that.

<ejs-treeview id="myTree" [fields]="treeFields"></ejs-treeview>

Once the data binding is done, the tree view will be rendered based on the data.


Load on demand

The tree view component was developed to work with large amounts of data. By default, the tree view is enabled with a load-on-demand option, so the child nodes were loaded at the time of expanding the parent node only.

Hence, even with a large amount of data bound to the tree view, it will load the first level nodes only, which results in the high performance.

Check boxes

Tree view has a built-in option for check boxes that allows the user to select more than one item.

The check boxes are applicable for all the parent and child nodes, where the parent nodes only allow the tri-state. When the child nodes are partially checked at that time, the parent node becomes tri-state.

We can enable check boxes by setting the showCheckBox property.

<ejs-treeview id="myTree" [fields]="treeFields" [showCheckBox]="true"></ejs-treeview>

Tree view has flexible APIs to set or get the checked nodes collection at any time, which helps while making interactive applications. Here you can check the nodes through the checkedNodes property. So, we can check a few nodes at the initial time like the following.

<ejs-treeview id="myTree" [fields]="treeFields" 
	[showCheckBox]="true" [checkedNodes]="['21','22','3']"></ejs-treeview>

And the tree view becomes like this image.


Node icons

Tree view has the option to render nodes with icons and images without node templating by mapping the iconCss and imageUrl fields to the node object. The iconCss adds a CSS class through which we can add font icons and custom styling. The imageUrl field inserts an image tag with the provided image path.

First, we can provide the node type details in the tree view data source, then based on that we will define the corresponding tree node’s icons. So, in our scenario, we will differentiate the nodes by folder type or any file type and will update the details in the data source with the additional column “nodeIcon”.

import { Component, OnInit, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css'],
  encapsulation: ViewEncapsulation.None,
})
export class HomeComponent implements OnInit {

  public treeData: Object[] = [
        {
            nodeId: '1', nodeText: 'Documents', nodeIcon: 'folder',
            nodeChild: [
                { nodeId: '11', nodeText: 'Team management.docx', nodeIcon: 'folder' },
                { nodeId: '12', nodeText: 'Entity Framework Core.pdf', nodeIcon: 'folder' }
            ]
        },
        {
            nodeId: '2', nodeText: 'Downloads', nodeIcon: 'folder', expanded: true,
            nodeChild: [
                { nodeId: '21', nodeText: 'Sales report.ppt', nodeIcon: 'ppt' },
                { nodeId: '22', nodeText: 'Introduction to Angular.pdf', nodeIcon: 'pdf' },
                { nodeId: '23', nodeText: 'Paint.exe', nodeIcon: 'exe' },
                { nodeId: '24', nodeText: 'TypeScript sample.zip', nodeIcon: 'zip' }
            ]
        },
        {
            nodeId: '3', nodeText: 'Music', nodeIcon: 'folder',
            nodeChild: [
                { nodeId: '31', nodeText: 'Crazy tone.mp3', nodeIcon: 'audio' }
            ]
        },
        {
            nodeId: '4', nodeText: 'Videos', nodeIcon: 'folder',
            nodeChild: [
                { nodeId: '41', nodeText: 'Angular tutorials.mp4', nodeIcon: 'video' },
                { nodeId: '42', nodeText: 'Basics of Programming.mp4', nodeIcon: 'video' }
            ]
        }
  ];

  public treeFields: Object = { 
    dataSource: this.treeData, 
    id: 'nodeId', 
    text: 'nodeText', 
    child: 'nodeChild',
    iconCss: 'nodeIcon'
  };

  constructor() { }

  ngOnInit() {

  }

}

Note: here the ViewEncapsulation set as None, since encapsulation is not applicable for dynamically created elements. Otherwise we need to put our custom styles understyles.css file.

An element is created for each node with the mentionediconCss class, so we can apply our styling for that node there. You can apply the following styles in the home.component.css file.

.e-treeview {
    border: 1px solid #ccc;
    width: 400px;
}
.e-treeview .e-list-icon {
    background-repeat: no-repeat;
    background-image: url('https://ej2.syncfusion.com/angular/demos/src/images/icons/file_icons.png');
    height: 20px;
}
.e-treeview .e-list-icon.folder { background-position: -10px -552px }
.e-treeview .e-list-icon.docx { background-position: -10px -20px }
.e-treeview .e-list-icon.ppt { background-position: -10px -48px }
.e-treeview .e-list-icon.pdf { background-position: -10px -104px }
.e-treeview .e-list-icon.zip { background-position: -10px -188px }
.e-treeview .e-list-icon.audio { background-position: -10px -244px }
.e-treeview .e-list-icon.video { background-position: -10px -272px }
.e-treeview .e-list-icon.exe { background-position: -10px -412px }

Now the tree view appearance will be changed.


Drag and drop

Another important option for tree view is node drag and drop. This allows the user to reorder the nodes through UI interaction.

We can enable the drag-and-drop option by setting the allowDragAndDrop property.

<ejs-treeview id="myTree" [fields]="treeFields" [allowDragAndDrop]="true"></ejs-treeview>

This behavior can be customized to prevent dropping into any nodes. This was widely used in applications similar to file manager where the drop can’t be allowed into the file-type nodes.

This can be achieved through the nodeDragging and nodeDragStop event.

<ejs-treeview id="myTree" [fields]="treeFields" [allowDragAndDrop]="true" 
	(nodeDragging)="onNodeDragging($event)" (nodeDragStop)="onNodeDragStop($event)"></ejs-treeview>

Apply the conditions in the corresponding event handler.

public onNodeDragging (e) {
    if(e.droppedNode && e.droppedNode.querySelector('.folder') == null) {
        // to show the node drop not allowed icon
        var dragItemIcon = document.querySelector(".e-treeview.e-drag-item .e-icon-expandable");
        dragItemIcon.classList.add('e-no-drop');
    }
}

public onNodeDragStop (e) {
    if(e.droppedNode.querySelector('.folder') == null) {
        // to prevent the node drop action
        e.cancel = true;
    }
}

Now you can see the tree view with drag and drop enabled, where you are not allowed to drop any files or folders under the file node.

Node editing

Node editing is also an often-used feature that allows the user to rename the tree node dynamically through UI interaction. This is also a common and useful option in applications similar to file manager.

We can enable the node editing option by setting the allowEditing property.

<ejs-treeview id="myTree" [fields]="treeFields" [allowEditing]="true"></ejs-treeview>

Now you can edit the tree nodes by double-clicking on them, or by pressing F2 key from the keyboard.


Template

The tree nodes can be templated using the built-in template support. This is a great option to give the tree view a great look and feel.

Depending on the application scenario, we can customize the tree nodes with images, multiple elements, and so on. Here, we can form a template for our file manager scenario to represent the child item count in the parent element.

First, we will update the data for the root elements to show the child count.

public treeData: Object[] = [
	{
		nodeId: '03', nodeText: 'Documents', nodeIcon: 'folder', childCount: 2,
		...
	},
	{
		nodeId: '05', nodeText: 'Downloads', nodeIcon: 'folder', expanded: true, childCount: 4,
		...
	},
	{
		nodeId: '01', nodeText: 'Music', nodeIcon: 'folder', childCount: 1,
		...
	},
	{
		nodeId: '02', nodeText: 'Videos', nodeIcon: 'folder', childCount: 2,
		...
	}
];

Then we can form the tree node element structure based on the childCount attribute.

<ejs-treeview id="myTree" [fields]="treeFields"><ng-template #nodeTemplate let-data><div>
            {{data.nodeText}}<span *ngIf="data.childCount" class="files-count">
                ({{data.childCount}} files)</span></div></ng-template></ejs-treeview>

Now add your custom styles for your template in home.component.css.

.files-count {
    font-size: 9px;
    color: red;
}

Finally, the tree view becomes like the following image.


Summary

Overall, the tree view component was designed to be completely customizable, as well as have flexible usage from the application point of view.

If you would like to try the tree view component, you can download our free trial. You can visit the tree view source in GitHub and you can check our sample browser and documentation for detailed explanation and the understanding to proceed further.

If you have any questions or need any clarifications, please let us know in the comments section below. You can also contact us through our support forum or Direct-Trac. We are always happy to assist you!


How to Start a Xamarin App from Scratch Webinar Q&A

$
0
0

On May 17, 2018, Syncfusion hosted the webinar, “How to Start a Xamarin App from Scratch,” presented by Aaron Melamed, Syncfusion’s product solutions specialist. Melamed showed attendees how to use Syncfusion’s navigation drawer and list view controls to set up a new Xamarin application. The following blog post is the Q&A portion of the webinar. The webinar recording can be found on our YouTube page, or you can watch it here.

 



Q: Could you please cover debugging issues with Xamarin.Forms? I regularly run into problems on Android and iOS. The only reliable build is UWP. Mostly, the problems are related to the linker. With PreserveAttribute, some issues are resolved, but not all. And even when the output project builds, it might not run or even install on a testing device. Do you have some debugging hints or best practice hints?

A: In Android, sometimes the existing application will be in cache even after uninstalling. Try uninstalling the cache from Apps under device settings, or renaming the package name under AndroidManifest.xml.

 

Q: I noticed that running your application using the Android emulator is quite fast. What kind of machine specs are you using for this demo? I am struggling together with my students: it takes forever to run and display something.

A: The demo was run on a Surface Book with an i7 and 16GB of RAM.

 

Q: One of my biggest challenges is creating a navigation command from a ViewModel. Do you have any advice?

A: Check out this Knowledge Base article:  https://www.syncfusion.com/kb/7520/how-to-navigate-page-from-viewmodel-using-button-in-listviewitem.

 

Q: How can you compile iOS using Windows?

A: A Mac build host is used to debug the iOS app from Windows. Please refer to this guide to learn more: https://docs.microsoft.com/en-us/xamarin/ios/get-started/installation/windows/connecting-to-mac/.

 

Q: Can we use Visual Code for building this app instead of Visual Studio?

A: No, Visual Studio must be used to build and deploy the code to a device or simulator.

 

Q: Can you discuss grouping in list view?

A: Please refer to this user guide document: https://help.syncfusion.com/xamarin/sflistview/getting-started#grouping.

 

Q: How do you navigate from the ViewModel to another page?

A: Check out this Knowledge Base article:  https://www.syncfusion.com/kb/7520/how-to-navigate-page-from-viewmodel-using-button-in-listviewitem.

 

Q: Is there any easy way to work with data?

A: Yes. We have a data source library. It is a non-UI component that consumes raw data and processes data operations such as sorting, filtering, and grouping, saving developers time and effort in building the functionality themselves.

 

Q: Can I use Syncfusion's other tools, like PDF converter?

A: Yes, check out our previous Xamarin webinar  for examples of our PDF controls in a Xamarin application.

 

Q: Can we make list view clickable and connect to different actions?

A: Yes, check out this Knowledge Base article: https://www.syncfusion.com/kb/7523/how-to-turn-events-into-commands-with-behaviors-in-sflistview.

 

Q: Is it possible to have a jump list in the list view?

A: Yes, we now have a pop-up control that allows this:  https://help.syncfusion.com/xamarin/sfpopuplayout/overview.


Create beautiful charts in Angular

$
0
0

In data visualization, charts play a vital role in representing data. If you’re looking for stunning charts for the Angular framework, the Essential JS 2 chart component provides them with a variety of impressive features.

In this blog, we are going to walk through the process of creating a simple chart in an Angular application and configuring the basic features. The complete code can be found at our GitHub repository.

Setting up the development environment

You should set up a development environment before creating a chart in Angular. Since the source is available in GitHub and packages are available in npm, you can get started with a chart in a few easy steps.

Creating an Angular application

To create an Angular application, install the Angular CLI globally using the following command.

npm install -g @angular-cli

Then create a new Angular application using the following command.

ng new my-app

 This command downloads all the files needed and initializes the npm installation.

Installing the chart component

After the Angular application has been created, use the following command to install the chart package.

cd my-app

npm install @syncfusion/ej2-ng-charts --save

The --save flag saves the charts package as a dependency in the package.json file.

Configuring the chart

All configuration related to environment setup is now complete. Before configuring the chart, a component is needed to render the chart. To create an Angular component, use the following Angular CLI command.

ng generate component chart

Next, import the chart module in the app.module.ts file.

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { ChartComponent } from './chart/chart.component';
import { ChartModule } from '@syncfusion/ej2-ng-charts’; 

@NgModule ({
 declarations: [AppComponent,ChartComponent],
 imports: [BrowserModule, ChartModule],
 bootstrap: [AppComponent]
})
export class AppModule { }

Creating the chart component

All configuration related to the chart is now complete. Now we need to define our first chart in the chart.component.html file.

<ejs-chart></ejs-chart>

Then, add the chart component in the app.component.html file.

<app-chart></app-chart>

Serving the application

Go to the application directory and launch the server by using following command.

ng serve -open

After all the files are compiled successfully, the basic chart should look like the following figure.

                                 

Injecting modules

Now we have the basic chart without data. Before providing some data to it, let’s learn more about the chart types that Syncfusion supports.

The Syncfusion chart component can plot more than 25 chart types. Each type is modularized and available as a separate service, so you can use only the modules you need, to keep your app lightweight. For example, if you want to visualize data with a column chart, define the columnSeriesService in the providers of the app.module.ts file. This service provides access to the column chart functionality.
import { ChartModule } from '@syncfusion/ej2-ng-charts';
import { CategoryService, ColumnSeriesService } from '@syncfusion/ej2-ng-charts';

@NgModule({
  imports: [ BrowserModule, ChartModule ],
  providers: [CategoryService, ColumnSeriesService ]
 })
After the columnSeriesService is injected in the providers, set the series type as Column and populate the data in the chart by using the dataSource property, which accepts a JavaScript object.
import {Component, OnInit } from '@angular/core';
@Component({
    selector: 'app-chart',
    template:`<ejs-chart id="chart-container" [primaryXAxis]="primaryXAxis"><e-series-collection><e-series [dataSource]="chartData" type="Column" xName="year" yName="gold" 
              name="Gold"> </e-series>              </e-series-collection></ejs-chart>`
})

export class AppComponent implements OnInit {
    public chartData: Object [];
    public primaryXAxis: Object; 
    ngOnInit(): void {
        // Data for chart series
        this.chartData = [
            { year:'2000', gold: 35, silver: 25 }, { year: '2001', gold: 28, silver: 20 },
            { year:'2002', gold: 34, silver: 21 }, { year: '2003', gold: 32, silver: 15 },
            { year:'2004', gold: 40, silver: 30 } 
         ];  
         this.primaryXAxis = { valueType: 'Category' };
    }

}
The populated column chart will look something like this:                                                                                                                                                                                           
                         
                                                                                            Populated Column Chart

Building other chart types

Implementing other Cartesian chart types is very similar to implementing the column chart. If you want an area or line chart, just inject its corresponding services in the providers and change the series type.

Let’s visualize some other set of data with a line chart type by adding another series to our column chart.

import { ChartModule } from '@syncfusion/ej2-ng-charts';
import { CategoryService, ColumnSeriesService, LineSeriesService} from '@syncfusion/ej2-ng-charts';

@NgModule({
imports: [ BrowserModule, ChartModule ],
providers: [CategoryService, ColumnSeriesService, LineSeriesService]
})
  `<ejs-chart id="chart-container" [primaryXAxis]="primaryXAxis"><e-series [dataSource]="chartData" type="Column" xName="year" yName="gold" name="Gold"><e-series [dataSource]="chartData" type="Line" xName="year" yName="silver" name="Silver"></ejs-chart>`
                   

Title

A chart can be given a title to inform users what to look for in the graph. The text of the title can be customized using the titleproperty.

`<ejs-chart id="chart-container" [primaryXAxis]="primaryXAxis" [title]="title"><e-series [dataSource]="chartData" type="Column" legendShape="Circle" xName="year" yName="gold" name="Gold"><e-series [dataSource]="chartData" type="Line" legendShape="Triangle" xName="year" yName="silver" name="Silver"></ejs-chart>`

export class AppComponent implements OnInit {
    public title: Object;
    public primaryXAxis: Object;
    ngOnInit(): void {
        this.primaryXAxis = { valueType: 'Category'  };
        this.title = 'Olympic Medal Count';
    }
}
                     

Legend

Another way end users can interact with the chart component is through a legend. You can access the legend functionality by injecting the LegendService in the providers. Also, you should set the visible property in the legendSettings to true.

Each series type has its own legend icon that will be displayed in the legend, and the name specified for the series will be displayed next to it. In the following code example, we are going to change the legend icons to rectangle and circle through the legendShapeproperty in the series.

import { ChartModule } from '@syncfusion/ej2-ng-charts';
import { CategoryService, ColumnSeriesService, LineSeriesService, LegendService } from '@syncfusion/ej2-ng-charts';
@NgModule({
    imports: [ BrowserModule, ChartModule ],
    providers: [CategoryService, ColumnSeriesService, LineSeriesService, LegendService]
   })
<ejs-chart id="chart-container" [primaryXAxis]="primaryXAxis" [legendSettings]="legendSettings"><e-series [dataSource]="chartData" type="Column" legendShape="Rectangle" xName="year" yName="gold" name="Gold"><e-series [dataSource]="chartData" type="Line" legendShape="Circle" xName="year" yName="silver" name="Silver"></ejs-chart>`

   export class AppComponent implements OnInit {  
      public title: Object;    
      public primaryXAxis: Object;
      public legendSettings: Object;
      ngOnInit(): void {  
         this.primaryXAxis = { valueType: 'Category' };      
         this.legendSettings = {visible : true};
    }
  }

After enabling the legend, the chart will appear as shown in the following figure. You can now interact with the legend to collapse or select the series you want.

                 

Data labels

Data labels are designed for situations where you want to improve the readability of your data. You can access the data label functionality by injecting the DataLabelServicein the providers and enabling the visibleproperty in the data labels.

The position of data labels can also be changed so that they are placed smartly. In the following code example, we are moving the data label for a column chart inside the bar by using the positionproperty.

import { ChartModule } from '@syncfusion/ej2-ng-charts';
import { CategoryService, ColumnSeriesService, LineSeriesService, LegendService, DataLabelService  } from '@syncfusion/ej2-ng-charts';

@NgModule({
imports: [ BrowserModule, ChartModule ],
providers: [CategoryService, ColumnSeriesService, LineSeriesService, LegendService, DataLabelService ]
 })

`<ejs-chart id="chart-container" [primaryXAxis]="primaryXAxis" [legendSettings]="legendSettings"><e-series [dataSource]="chartData" type="Column" legendShape="Circle" xName="year" yName="gold" name="Gold" [marker]="columnMarker"><e-series [dataSource]="chartData" type="Line" legendShape="Triangle" xName="year" yName="silver" name="Silver" [marker]="lineMarker"></ejs-chart>`

   export class AppComponent implements OnInit {
    public title: Object;
    public primaryXAxis: Object;
    public legendSettings: Object;
    public lineMarker : Object;
    public columnMarker : Object;
    ngOnInit(): void {       
        this.primaryXAxis = { valueType: 'Category' };      
        this.legendSettings = {visible : true};      
        this.columnMarker = { dataLabel : { visible :true, position: 'Top'}};
        this.lineMarker = { visible : true, dataLabel : { visible :true }};
    }
}

After enabling data labels, our chart will appear as follows.

                       

Tooltips

You can also provide more information about chart data points when pointing to them by using tooltip. To make use of the tooltip functionality, just inject the TooltipService in the provider and enable the tooltip by setting the enable property to true

import { ChartModule } from '@syncfusion/ej2-ng-charts';
import { CategoryService, ColumnSeriesService, LineSeriesService, DataLabelService, LegendService, TooltipService  } from '@syncfusion/ej2-ng-charts';
@NgModule({
imports: [ BrowserModule, ChartModule ],
providers: [CategoryService, ColumnSeriesService, LineSeriesService, DataLabelService, LegendService, TooltipService ]
 })  
`<ejs-chart id="chart-container" [primaryXAxis]="primaryXAxis" [legendSettings]="legendSettings" [tooltip]="tooltip"><e-series [dataSource]="chartData" type="Column" legendShape="Circle" xName="year" yName="gold" name="Gold" [marker]="columnMarker"><e-series [dataSource]="chartData" type="Line" legendShape="Triangle" xName="year" yName="silver" name="Silver" [marker]="lineMarker"></ejs-chart>`

export class AppComponent implements OnInit {
    public title: Object;
    public primaryXAxis: Object; 
    public legendSettings: Object;
    public lineMarker : Object;
    public columnMarker : Object;
    public tooltip : Object;
    ngOnInit(): void {
        this.primaryXAxis = { valueType: 'Category'  };
        this.legendSettings = {visible : true};
        this.columnMarker = { dataLabel : { visible :true, position: 'Top'}};
        this.lineMarker = { dataLabel : { visible :true }};
        this.tooltip = {enable : true};
    }
}
                         

Conclusion

In this blog, we learned how to create a simple chart and enhance its basic features. The chart component offers many other advanced features, such as data binding with different adaptors, zooming, selection, trackball, crosshair, financial charts, polar and radar charts, pie charts, annotations, axis types, strip lines, and much more.

We recommend checking out the chart component on your own through the source on GitHub, the interactive sample browser, and the documentation to explore all of its features and API. Also, be sure to check out the chart sample on GitHub, which is readily runnable, to see just how easy it is to create and configure charts.

Hoping the chart is available for other frameworks? You’re in luck. It’s currently available for ASP.NET Core, ASP.NET MVC, JavaScript, and React, and will soon be available for Vue as well (expect in the 2018 Volume 2 release).

If you have any questions or comments, please let us know in the comments below. You can also contact us through our support forum or Direct-Trac. We are happy to assist you!

Designing Airfare Calendar Using Pure JavaScript Scheduler

$
0
0

For anyone who is looking for flight availability, checking for the lowest available airfare is the very first thing you do. Isn’t it nice when a single calendar can show you the lowest prices of all available flights on each day of a month for a specific route? Let’s walk through how to customize the scheduler  component to design an airfare calendar displaying these lowest prices.

Before starting with the customization part, let’s go through an overview of the basic functionalities available in scheduler.

Overview

Scheduling can be anything that relates to a date and time. With our pure JavaScript scheduler component (Essential JS 2), you can plan and manage events or tasks during any specific interval of time. You can easily customize all the schedule elements based on your application-specific needs.

Built-in views

There are six display modes availableday, week, work week, month, agenda, and month agendaout of which week mode is displayed as an active view. Each view can have its own set of configurations, allowing the same feature to be exhibited with different values on each view. 

To navigate among views and dates, navigation options are available on the schedule header bar. The date range of the active view will also be displayed in the header bar, and clicking on it will open a calendar pop-up for ease of date selection.

Module injection

Module injection plays a vital role in our pure JavaScript platforms, as each schedule view is maintained as an individual module. Therefore, to work with specific views, the appropriate module needs to be first injected into the application. For example, to work only with the day view on scheduler, it is enough to inject the Day module alone.

Binding appointment data

Providing start and end time data is enough to display appointments in the scheduler.

import { Schedule, Day, Week, WorkWeek, Month, Agenda } from '@syncfusion/ej2-schedule';

Schedule.Inject(Day, Week, WorkWeek, Month, Agenda);

let scheduleObj: Schedule = new Schedule({
    height: '550px',
    selectedDate: new Date(2018, 1, 15),
    eventSettings: {
        dataSource: [{
            Subject: 'Prayer Time',
            StartTime: new Date(2018, 1, 15, 9, 30),
            EndTime: new Date(2018, 1, 15, 10, 30)
        }, {
            Subject: 'Lunch Break',
            StartTime: new Date(2018, 1, 15, 13, 30),
            EndTime: new Date(2018, 1, 15, 14, 30)
        }]
    }
});
scheduleObj.appendTo('#Schedule');

To bind the data with different field names rather than the default available ones, map them accordingly using the fields mapping property as shown.

let scheduleObj: Schedule = new Schedule({
    height: '550px',… 
    …
    eventSettings: {
        dataSource: [{
           Id: 12,
           Departure: new Date(2018, 1, 11, 9, 30),
           Arrival: new Date(2018, 1, 11, 11, 30),
           Fare: "110.34"
        },
        {
           Id: 13,
           Departure: new Date(2018, 1, 11, 15, 30),
           Arrival: new Date(2018, 1, 11, 17, 30),
           Fare: "115.28"
        }],
        fields: {
            id: { name: "Id" },
            startTime: { name: "Departure" },
            endTime: { name: "Arrival" },
            subject: { name: "Fare" }
        }
    }
});

Customizing scheduler to display airfare calendar

Let’s display only the month view for this customization. To achieve this, inject only the Month module using the code Schedule.Inject(Month). The lowest price available on each day needs to be displayed as appointments with style customization applied to them using a template option.

Here, the entire flight data of a specific month needs to be sorted based on the available fares. Since we’ve planned to display only a single piece of data per day, restrict the total data count to be the number of days of a month and assign only that filtered data count to the scheduler dataSource.

Other than these functionalities, we will also highlight the day of a month that has the comparatively overall lowest price.

Getting started

To build and run a new Essential JS 2 application in TypeScript, make use of the QuickStart project from GitHub and also install the necessary packages using the following command line.

Choose an appropriate path in your system and navigate to that path in the command prompt. Then type in the following commands one by one.

git clone https://github.com/syncfusion/ej2-quickstart.git quickstart
cd quickstart
npm install

The npm install command will install all the needed JS 2 packages in the quickstart project. Now you can start directly adding the scheduler component-related code to it.

An additional step before starting to code is to check the settings within your system.config.js file, to see whether the schedule component’s dependency packages are mapped appropriately, as shown in the following code listing.

System.config({
    paths: {
        'npm:': './node_modules/',
        'syncfusion:': 'npm:@syncfusion/'
    },
    map: {
        app: 'app',
        //Syncfusion packages mapping
        "@syncfusion/ej2-base": "syncfusion:ej2-base/dist/ej2-base.umd.min.js",
        "@syncfusion/ej2-data": "syncfusion:ej2-data/dist/ej2-data.umd.min.js",
        "@syncfusion/ej2-inputs": "syncfusion:ej2-inputs/dist/ej2-inputs.umd.min.js",
        "@syncfusion/ej2-buttons": "syncfusion:ej2-buttons/dist/ej2-buttons.umd.min.js",
        "@syncfusion/ej2-lists": "syncfusion:ej2-lists/dist/ej2-lists.umd.min.js",
        "@syncfusion/ej2-navigations": "syncfusion:ej2-navigations/dist/ej2-navigations.umd.min.js",
        "@syncfusion/ej2-dropdowns": "syncfusion:ej2-dropdowns/dist/ej2-dropdowns.umd.min.js",
        "@syncfusion/ej2-popups": "syncfusion:ej2-popups/dist/ej2-popups.umd.min.js",
        "@syncfusion/ej2-calendars": "syncfusion:ej2-calendars/dist/ej2-calendars.umd.min.js",
        "@syncfusion/ej2-schedule": "syncfusion:ej2-schedule/dist/ej2-schedule.umd.min.js"
    },
    packages: {
        'app': { main: 'app', defaultExtension: 'js' }
    }
});
System.import('app');

Ensure the CSS is referenced properly within the [src/styles/styles.css] file with the following code.

@import '../../node_modules/@syncfusion/ej2/material.css';

Using scheduler component

Now, define a div element with an ID to represent scheduler within the body section of your index.html file, as shown in the following code listing. To learn more basic details about how to get started with  our pure JavaScript controls, refer to our documentation.

<!DOCTYPE html><html lang="en"><head><title>Essential JS 2</title><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" /><meta name="description" content="Essential JS 2" /><meta name="author" content="Syncfusion" /><link rel="shortcut icon" href="resources/favicon.ico" /><link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" /><!--style reference from node_modules/@syncfusion/ej2/--><link href="https://blog.syncfusion.com/styles/styles.css" rel="stylesheet" /><script src="node_modules/systemjs/dist/system.src.js" type="text/javascript"></script><script src="system.config.js" type="text/javascript"></script></head><body><div style="margin: 50px;"><!-- Element to be rendered as Schedule --><div id="Schedule"></div></div></body></html>

To render the scheduler on a page, import and initialize it within the app.ts file, as shown in the next code listing. Using the module injection method, inject only the Month module, using Schedule.Inject(Month)

Set the required properties, such as height, views and selectedDate.

viewsTo set a specific view in schedule. Here, we will be using only month view.

readonlyTo prevent CRUD-related actions from being performed in a schedule.

selectedDateTo make the schedule display with this provided date.

/**
 * The need for importing DataManager-related items is described in the appropriate section.
*/
import { Schedule, Month } from '@syncfusion/ej2-schedule';
import { DataManager, Query, Predicate } from '@syncfusion/ej2-data';

/**
 * Inject only month view here.
*/
Schedule.Inject(Month);

/**
 * Schedule defined with readonly mode, as we are simply displaying the fare details and no interactions on it.
*/
    let scheduleObj: Schedule = new Schedule({
        height: '550px',
        views: ['Month'],
        readonly: true,
        selectedDate: new Date(2018, 3, 1)
    });
    scheduleObj.appendTo('#Schedule');

To prevent any of the pop-ups from opening while clicking on the scheduler appointments or cells, make use of the popupOpen event and define args.cancel as true within it.

/**
 * PopupOpenEventArgs needs to be imported to use the arguments of popupOpen event.
*/
import { Schedule, Month, PopupOpenEventArgs } from '@syncfusion/ej2-schedule';
import { DataManager, Query, Predicate } from '@syncfusion/ej2-data';

/**
 * Inject only month view here.
*/
Schedule.Inject(Month);

/**
 * Schedule defined with readonly mode, as we are simply displaying the fare details and no interactions on it.
*/
    let scheduleObj: Schedule = new Schedule({
        height: '550px',
        views: ['Month'],
        readonly: true,
        selectedDate: new Date(2018, 3, 1),

/**
 *  `popupOpen` is an event that triggers before any of the pop-ups opens on scheduler.
*/
        popupOpen: (args: PopupOpenEventArgs) => {
            args.cancel = true;
        }
    });
    scheduleObj.appendTo('#Schedule');

Populating required data

Let’s assume we have the dataSource object with the following flight data: departure, arrival, airline name, fare, and other related fields, if needed. Let’s compare the rates of three flights per day on a specific route for the month of April 2018.

Since data for three flights a day for a whole month will be huge to define and handle here, for demo purposes, we are generating the random data object of count 90 with the required fields (three appointments per day for 30 days) through looping as defined in the following function.

function generateEvents(): Object[] {
    let collections: Object[] = [];
    let dataCollections: { [key: string]: Object }[] = [
        {
            Id: 100,
            Departure: new Date(2018, 3, 1, 8, 30),
            Arrival: new Date(2018, 3, 1, 10, 0),
            AirlineId: 1
        }, {
            Id: 102,
            Departure: new Date(2018, 3, 1, 11, 0),
            Arrival: new Date(2018, 3, 1, 12, 0),
            AirlineId: 2
        }, {
            Id: 103,
            Departure: new Date(2018, 3, 1, 14, 0),
            Arrival: new Date(2018, 3, 1, 15, 0),
            AirlineId: 3
        }
    ];
    let start: Date = new Date(2018, 3, 1);
    let dateCollections: Date[] = Array.apply(null, { length: 30 })
        .map((value: number, index: number) => { return new Date(start.getTime() + (1000 * 60 * 60 * 24 * index)); });
    let id: number = 1;
    let day: number = 0;
    for (let date of dateCollections) {
        let resource: number = 1;
        for (let data of dataCollections) {
            let strDate: Date = new Date((<date>data.Departure).getTime());
            let endDate: Date = new Date((<date>data.Arrival).getTime());
            collections.push({
                Id: id,
                Departure: new Date(strDate.setDate(strDate.getDate() + day)),
                Arrival: new Date(endDate.setDate(endDate.getDate() + day)),
                AirlineId: resource,
                Fare: ((Math.random() * 500) + 100).toFixed(2)
            });
            resource += 1;
            id += 1;
        }
        day += 1;
    }
    return collections;
}

Now the data collection is ready, and we need to filter it based on the lowest fare per day, with a logic as given in the following.

function filterByFare(start: Date, dateCollections: Date[], appointments: Object[]): Object[] {
    let finalData: Object[] = [];
    for (let date of dateCollections) {
        let strTime: Date = new Date(+date);
        let endTime: Date = new Date(new Date(strTime.getTime()).setHours(23, 59, 59, 59));
        let predicate: Predicate = new Predicate('Departure', 'greaterthanorequal', strTime).
            and(new Predicate('Arrival', 'greaterthanorequal', strTime)).
            and(new Predicate('Departure', 'lessthan', endTime)).
            or(new Predicate('Departure', 'lessthanorequal', strTime).
                and(new Predicate('Arrival', 'greaterthan', strTime)));
        let filteredEvents: Object[] = new DataManager({ json: appointments }).executeLocal(new Query().where(predicate));
        let perDayData: Object[] = filteredEvents;
        if (perDayData.length > 0) {
            perDayData.sort((a: { [key: string]: Object }, b: { [key: string]: Object }) => ((<number>a.Fare) - (<number>b.Fare)));
            finalData.push(perDayData[0]);
        }
    }
    return finalData;
}

NOTE: In the previous code, we have used the data manager-related code to make use of the data manager, and it is necessary to import its necessary items from @syncfusion/ej2-data.

Filtering based on fare needs to be called within the generateEvents method before returning the result, as follows.

function generateEvents(): Object[] {
    let collections: Object[] = [];…
    …
    …
    let filteredCollection: Object[] = filterByFare(start, dateCollections, collections);
    return filteredCollection;
}

The filtering process on the data collection is done and it is time to assign it to the schedule’s dataSource and display it on the scheduler. Now, each day will hold exactly one appointment, as per the filtering result.

let scheduleObj: Schedule = new Schedule({
    height: '550px',…
    …
    eventSettings: {
        dataSource: generateEvents(),
        fields: {
            id: { name: "Id" },
            startTime: { name: "Departure" },
            endTime: { name: "Arrival" },
            subject: { name: "Fare" }
        }
    }
});

Also, the appropriate fields given in the dataSource are mapped onto scheduler through the fields property.

Appearance customization

The readonly scheduler now displays with our provided flight data in a usual appointment style. To customize the appearance of it, we need to define the template option within the eventSettings property.

The template definition can be referenced from the following and its ID needs to be mapped to the template option of eventSettings property. Also, the styles used to customize the events need to be defined within the index.html file.

// Template design for appointments to be defined within the index.html file<script id="apptemplate" type="text/x-template"><div class='template-wrap'><div class='fare-detail'>$${Fare}</div><div class='airline-name' style='display:flex;padding-left:5px;'><div class="airline-logo ${getImage(data.AirlineId)}"></div><div class='airway-name'>${getName(data.AirlineId)}</div></div></div></script>

// Styles to be applied to events
<style type="text/css">
    .e-schedule .e-appointment .template-wrap {
        width: 100%;
    }

    .e-schedule .template-wrap .airline-logo {
        background-size: cover;
        margin-top: -3px;
        width: 25px;
        height: 25px;
    }

    .e-schedule .template-wrap .airline-logo.air1 {
        background: url('http://npmci.syncfusion.com/development/demos/src/schedule/images/airways-1.svg') no-repeat 50% 50%;
    }

    .e-schedule .template-wrap .airline-logo.air2 {
        background: url('http://npmci.syncfusion.com/development/demos/src/schedule/images/airways-2.svg') no-repeat 50% 50%;
    }

    .e-schedule .template-wrap .airline-logo.air3 {
        background: url('http://npmci.syncfusion.com/development/demos/src/schedule/images/airways-3.svg') no-repeat 50% 50%;
    }

    .e-schedule .fare-detail {
        color: #00837B;
        font-size: 16px;
        font-weight: 500;
        height: 25px;
        padding-left: 5px;
    }

    .e-schedule.e-device .fare-detail {
        font-size: 11px;
    }

    .e-schedule .airway-name {
        font-size: 12px;
        overflow: hidden;
        padding-left: 5px;
        text-overflow: ellipsis;
        color: rgba(0,0,0,0.87);
    }

    .e-schedule.e-device .airway-name {
        display: none;
    }

    .e-schedule .e-month-view .e-appointment {
        height: 45px;
        background: none;
        border-width: 0;
        top: 10px !important;
    }

    .e-schedule.e-device .e-month-view .e-appointment {
        height: 40px;
    }

    .e-schedule .e-month-view .e-appointment .e-appointment-details {
        height: inherit;
    }

    .e-schedule .e-month-view .e-appointment.e-appointment-border,
    .e-schedule .e-month-view .e-appointment:focus {
        border-width: 0;
    }
</style>

In the previous template definition, we made a function call to get the airway name and image based on the airline ID, which needs to be defined appropriately within the app.ts file.

interface TemplateFunction extends Window {
    getImage?: Function;
    getName?: Function;
}

// Below function to be defined within the .ts file
(window as TemplateFunction).getImage = (value: number) => {
    return (value === 1) ? 'air1' : (value === 2) ? 'air2' : 'air3';
};

(window as TemplateFunction).getName = (value: number) => {
    return (value === 1) ? 'Airways 1' : (value === 2) ? 'Airways 2' : 'Airways 3';
};

All is done and now the final thing is to highlight the overall lowest fare date of a month. To do so, we will make use of the dataBound event, within which we will check for the lowest fare for the month.

import { Schedule, Month } from '@syncfusion/ej2-schedule';
import { DataManager, Query, Predicate } from '@syncfusion/ej2-data';

/**
 * Inject only month view here.
*/
Schedule.Inject(Month);

/**
 * Interface for defining template function
*/

interface TemplateFunction extends Window {
    getImage?: Function;
    getName?: Function;
}

// Below function to be defined within the .ts file
(window as TemplateFunction).getImage = (value: number) => {
    return (value === 1) ? 'air1' : (value === 2) ? 'air2' : 'air3';
};

(window as TemplateFunction).getName = (value: number) => {
    return (value === 1) ? 'Airways 1' : (value === 2) ? 'Airways 2' : 'Airways 3';
};

/**
 * Schedule defined with readonly mode, as we are simply displaying the fare details and no interactions on it.
*/
let scheduleObj: Schedule = new Schedule({
    height: '550px',
    views: ['Month'],
    readonly: true,
    showHeaderBar: false, // To hide the header bar
    selectedDate: new Date(2018, 3, 1),
    eventSettings: {
        template: "#apptemplate",
        dataSource: generateEvents(),
        fields: {
            id: { name: "Id" },
            startTime: { name: "Departure" },
            endTime: { name: "Arrival" },
            subject: { name: "Fare" }
        }
    },

/**
 *  `popupOpen` is an event that triggers before any of the pop-ups opens on scheduler.
*/
    popupOpen: (args: PopupOpenEventArgs) => {
        args.cancel = true;
    },

/**
 * To customize and highlight the cell background of the cell that has the best offer.
*/
    dataBound: () => {
        let eventCollections: Object[] = scheduleObj.getCurrentViewEvents();
        eventCollections.sort((a: { [key: string]: Object }, b: { [key: string]: Object }) =>
            ((<number>a.Fare) - (<number>b.Fare)));
        let indexDate: Date = new Date((<date>(<{ [key: string]: Object }>eventCollections[0]).Departure).getTime());
        indexDate.setHours(0, 0, 0, 0);
        let index: number = scheduleObj.getIndexOfDate(scheduleObj.activeView.renderDates, indexDate);
        let target: HTMLElement = scheduleObj.element.querySelectorAll('.e-work-cells')[index] as HTMLElement;
        target.style.background = '#FFFBDF';
    }
});

Summary

In summary, we have seen how to customize the scheduler through its built-in properties, using additional styling options to display it as an airfare calendar. Stay tuned, we will write more blogs showing how to customize scheduler in more enhanced ways to achieve other use case scenarios.

Try our scheduler component by downloading from the free trial or GitHub. Feel free to have a look at our online samples and documentation to explore other available options. If you have any queries or require clarification, please let us know in the comments section below. You can also contact us through our support forum or Direct-Trac. We are always happy to assist you!

You can download the complete sample from GitHub.

Interactive Form Filling in Four Easy Steps

$
0
0

An interactive form, sometimes referred to as an AcroForm, is a collection of fields for gathering information interactively from the user. A PDF document may contain any number of fields appearing on any combination of pages, all of which make up a single, global interactive form spanning the entire document.

The Syncfusion PDF viewer for WPF and UWP platforms supports form filling, which allows the user to fill in and edit form fields. The user can save, print, and flatten the filled form. It is supported from the 2016 Volume 3 release (version 14.3.0.49) onwards in WPF applications and the 2018 Volume 1 SP1 release (version 16.1.0.32) in UWP applications. The following are some of the use case scenarios in which the interactive form filling using PDF viewer can be useful:


  • Event registration
  • Employment application
  • Car rental checklist

Here in this blog, we will look into filling an event registration form.


Fill the form in the PDF document

The PDF viewer supports filling and editing the following form fields:


  • Text boxes
  • Combo boxes
  • Radio buttons
  • Check boxes
The existing values of all these controls can be edited. PDF viewer also preserves tab order in navigating among the form fields when pressing Tab key.
 

Prepare a simple application with PDF viewer control by referencing the UG documentation and loading the event registration document. This document contains form fields to fill in basic details about the participant. Fill the form with the requested details.


Save the filled form

After entering the details, the save button in the toolbar can be used to save the filled form PDF document in a desired location. Once the saved document is opened in PDF viewer, the filled in information will persist in the document.


Print the filled form

In a similar fashion, the print button in the document toolbar can be used to print the filled PDF document using the viewer. On clicking or tapping the print button in the toolbar, a print dialog will be prompted, which is used to acquire the printer settings for printing the document.


Flatten and save the filled form

This feature can be used to transform an interactive PDF document into a noninteractive PDF. An interactive PDF document lets users enter or modify data that is in the PDF document fields. The process of transforming an interactive PDF document to a noninteractive PDF document is called flattening. When a PDF document is flattened, a user cannot modify the data in the document fields. One reason to flatten a PDF document is to ensure that data cannot be modified.


After filling the PDF document, the LoadedDocument property of the PdfViewerControl instance can be used to acquire the filled PDF document. Then, flattening the form fields and saving the PdfLoadedDocument object will result in a flattened PDF document. The below code snippet illustrates the same.


PdfLoadedDocument loadedDocument = pdfViewerControl.LoadedDocument;
loadedDocument.Form.Flatten = true;
loadedDocument.Save("Output.pdf");

A sample demonstrating filling the form fields, saving, and printing them using the PDF viewer can be downloaded from here: FormFillingDemo.zip.

Summary

As you can see, the Syncfusion PDF viewer supports filling a variety of form fields in a PDF document. It also supports saving, printing, and flattening the filled PDF document.


If you’re already a Syncfusion user, you can download the product setup here. If you’re not yet a Syncfusion user, you can download a free, 30-day trial here.


If you have any questions or require clarification on these features, please let us know in the comments below. You can also contact us through our support forum or Direct-Trac. We are happy to assist you!

Interview with MonoGame Succinctly Author Jim Perry

$
0
0

The following is a short interview with Succinctly series author Jim Perry, whose latest book,MonoGame Succinctly,was published recently. You can download the book here.


What should people know about MonoGame? Why is it important?

MonoGame is a multi-platform SDK that allows developers to write virtually the same code they used for making XNA games. It allows former XNA developers to update their games and port their games to other platforms, easing the development of games.

When did you first become interested in MonoGame?

When XNA started dying I looked at other tools for game development. As MonoGame continued to become more compatible with my old XNA code, it became a good solution for creating games with minimal effort.

By writing this e-book, did you learn anything new yourself?

I hadn't kept up with the most recent capabilities of MonoGame as I've been using Unity for my game development. It was a pleasant surprise to see the platforms it's grown to support and the functionality it gives game developers.

How will MonoGame change over the next few years?

If contributors keep updating the source it will be a good solution for game developers looking to use C# and/or old XNA code for creating games.

Do you see MonoGame as part of a larger trend in software development?

Open source software continues to be a good trend in software development. Game development is a huge business and there are plenty of opportunities for developers to enter the space.

 

What other books or resources on this topic do you recommend?

The main MonoGame site is probably the best resource to keep an eye on. MonoGame is still a fairly niche toolset for game development so there aren’t a lot of other resources.

Guest Blog: Why I Read the Succinctly Series

$
0
0

The following guest blog was written by Maximilian Hartmann, a student at ETH Zurich.


Students or anyone willing to advance in new fields of study are constantly seeking quality and preferably free sources of education to start out with. Nowadays, YouTube is one of the first places to look for in-depth tutorials about anything without spending a dime, just to get a first glimpse of the topic to hopefully confirm one’s initial interest.

From my point of view, all this graphical and audio-based material is awesome but still not entirely sufficient to quench one’s thirst for knowledge, especially when you get stuck and need a reliable source to fall back onto. That’s why I am personally always on the lookout for nicely written books, or in the age of the Internet, mostly e-books that give the reader a structured overview of an entire topic. After a seemingly endless amount of time trying to find my lecturer’s books on torrent sites or basically any corner of the deep web (joking), I decided to look in a different direction. I used my profound Google tech skills, including the command “filetype:pdf” and some keywords related to the scripting language Python and the statistical computing project R to finally stumble upon the Succinctly series. Even though there was a huge variety of openly available e-books on the first page of the Google search results (nobody is so desperate to dig deeper than that), the books provided by the Succinctly series impressed me not only by their cover design but also by their high-quality authors. For example, I was already familiar with Jason Cannon, the author of Python Succinctly, through books he had written about Linux as well as his YouTube channel where he provides additional free Linux-related tutorials.

I am not a big programmer myself. My study is not linked to computer science nor heavy scripting. Nevertheless, my own impression is that nobody can completely avoid being confronted by it in the long run, especially in today’s increasingly digitized world. Also, everybody has tedious tasks they would rather assign to a computer to do while having a beer. The Succinctly series books provided me with a solid foundation to be able to write small scripts and fostered my general interest in programming, even to this day. Because of the Succinctly series, I was able to write a Python script to read, compare, and graphically output radio spectrometry data for my bachelor’s thesis. For this I want to thank everybody involved who made this possible and continues to provide quality content.

Introducing New Angular Tree View Component in Essential JS 2

$
0
0

The tree view control is used to represent hierarchical data in a tree-like structure, with the option of expanding and collapsing the tree nodes. Tree view has many flexible options, including data binding, node icon support, check boxes, node templates, drag and drop, and node editing supports.

This blog provides an overview of the tree view control from Essential JS 2, and also shows you the basic usage and the features of tree view.

Getting started

We can see how to gets started with the tree view component in the Angular platform through the following simple steps:

  1. First, we can create a basic Angular application through theangular-cli. If you don’t have the CLI tool already, then you can install it globally with the following command.
  2. npm install -g @angular/cli

  3. Create an Angular application using the following command.
  4. ng new treeview-app

    This will create the application and download its dependencies.

  5. Once the application is created, you can install the packages for tree view component into your application by using the following command.
  6. cd treeview-app
    npm install @syncfusion/ej2-ng-navigations --save

    Here, --save will include the navigations package in the dependencies list of package.json.

  7. Now, the environment-related configurations are completed. Next, you can create a component to place the tree view inside. You can use the following command to create a component in your application.
  8. ng generate component home

    After that, the following files will be created.

    CREATE src/app/home/home.component.html (23 bytes)
    CREATE src/app/home/home.component.spec.ts (614 bytes)
    CREATE src/app/home/home.component.ts (261 bytes)
    CREATE src/app/home/home.component.css (0 bytes)
    UPDATE src/app/app.module.ts (388 bytes)

    Then you need to import the tree view component inapp.module.ts, and include it in the declarations.

    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    
    import { AppComponent } from './app.component';
    import { HomeComponent } from './home/home.component';
    
    import { TreeViewComponent } from '@syncfusion/ej2-ng-navigations';
    
    @NgModule({
      declarations: [
        AppComponent,
        HomeComponent,
        TreeViewComponent
      ],
      imports: [
        BrowserModule
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule { }

  9. Essential JS 2 components support a set of built-in themes, and here we will use the Material theme for the tree view. To add the material theme in your application, you need to import material.css in styles.css.
  10. @import '../node_modules/@syncfusion/ej2-ng-navigations/styles/material.css';

  11. We have successfully completed the configurations related to tree view. Now you need to initialize your first tree view component in home.component.html.
  12. <ejs-treeview id="myTree"></ejs-treeview>

    Then add the home component in app.component.html (or where you want to place the tree view).

    <div style="text-align:center"><h1>
        Welcome to the Angular TreeView sample!</h1></div><app-home></app-home>

  13. Finally, run the following command to see the output in a browser.
  14. ng serve --open

    Note: Now tree view is rendered without any nodes, since data binding is essential for this.

Data binding

Undoubtedly, tree view is a data-bound component that will need to be bound with a data source. The data source should be in the form of any valid hierarchical structure such as XML, a nested array of JSON objects, or a self-referential structure.

The tree nodes will be rendered from the dataSource based on the fields property, where the following columns are mandatory to display a tree view:

  • Text - defines the display text of the tree node.
  • Child - defines the child data source to render the sub-nodes (children nodes).

If the data source has different column names, then we should map those names through the fields property.

Now we can construct simple hierarchical data in home.component.ts, and map it to the tree view fields.

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {

  public treeData: Object[] = [
        {
            nodeId: '1', nodeText: 'Documents',
            nodeChild: [
                { nodeId: '11', nodeText: 'Team management.docx' },
                { nodeId: '12', nodeText: 'Entity Framework Core.pdf' },
            ]
        },
        {
            nodeId: '2', nodeText: 'Downloads',
            nodeChild: [
                { nodeId: '21', nodeText: 'Sales report.ppt' },
                { nodeId: '22', nodeText: 'Introduction to Angular.pdf' },
                { nodeId: '23', nodeText: 'Paint.exe' },
                { nodeId: '24', nodeText: 'TypeScript sample.zip' },
            ]
        },
        {
            nodeId: '3', nodeText: 'Music',
            nodeChild: [
                { nodeId: '31', nodeText: 'Crazy tone.mp3' }
            ]
        },
        {
            nodeId: '4', nodeText: 'Videos',
            nodeChild: [
                { nodeId: '41', nodeText: 'Angular tutorials.mp4' },
                { nodeId: '42', nodeText: 'Basics of Programming.mp4' },
            ]
        }
  ];

  public treeFields: Object = { 
    dataSource: this.treeData, 
    id: 'nodeId', 
    text: 'nodeText', 
    child: 'nodeChild' 
  };

  constructor() { }

  ngOnInit() {

  }

}

Initialize the tree view in home.component.html, and assign the fields to that.

<ejs-treeview id="myTree" [fields]="treeFields"></ejs-treeview>

Once the data binding is done, the tree view will be rendered based on the data.

style="width: 314.5px; float: none;">

Load on demand

The tree view component was developed to work with large amounts of data. By default, the tree view is enabled with a load-on-demand option, so the child nodes were loaded at the time of expanding the parent node only.

Hence, even with a large amount of data bound to the tree view, it will load the first level nodes only, which results in the high performance.

Check boxes

Tree view has a built-in option for check boxes that allows the user to select more than one item.

The check boxes are applicable for all the parent and child nodes, where the parent nodes only allow the tri-state. When the child nodes are partially checked at that time, the parent node becomes tri-state.

We can enable check boxes by setting the showCheckBox property.

<ejs-treeview id="myTree" [fields]="treeFields" [showCheckBox]="true"></ejs-treeview>

Tree view has flexible APIs to set or get the checked nodes collection at any time, which helps while making interactive applications. Here you can check the nodes through the checkedNodes property. So, we can check a few nodes at the initial time like the following.

<ejs-treeview id="myTree" [fields]="treeFields" 
	[showCheckBox]="true" [checkedNodes]="['21','22','3']"></ejs-treeview>

And the tree view becomes like this image.


Node icons

Tree view has the option to render nodes with icons and images without node templating by mapping the iconCss and imageUrl fields to the node object. The iconCss adds a CSS class through which we can add font icons and custom styling. The imageUrl field inserts an image tag with the provided image path.

First, we can provide the node type details in the tree view data source, then based on that we will define the corresponding tree node’s icons. So, in our scenario, we will differentiate the nodes by folder type or any file type and will update the details in the data source with the additional column “nodeIcon”.

import { Component, OnInit, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css'],
  encapsulation: ViewEncapsulation.None,
})
export class HomeComponent implements OnInit {

  public treeData: Object[] = [
        {
            nodeId: '1', nodeText: 'Documents', nodeIcon: 'folder',
            nodeChild: [
                { nodeId: '11', nodeText: 'Team management.docx', nodeIcon: 'folder' },
                { nodeId: '12', nodeText: 'Entity Framework Core.pdf', nodeIcon: 'folder' }
            ]
        },
        {
            nodeId: '2', nodeText: 'Downloads', nodeIcon: 'folder', expanded: true,
            nodeChild: [
                { nodeId: '21', nodeText: 'Sales report.ppt', nodeIcon: 'ppt' },
                { nodeId: '22', nodeText: 'Introduction to Angular.pdf', nodeIcon: 'pdf' },
                { nodeId: '23', nodeText: 'Paint.exe', nodeIcon: 'exe' },
                { nodeId: '24', nodeText: 'TypeScript sample.zip', nodeIcon: 'zip' }
            ]
        },
        {
            nodeId: '3', nodeText: 'Music', nodeIcon: 'folder',
            nodeChild: [
                { nodeId: '31', nodeText: 'Crazy tone.mp3', nodeIcon: 'audio' }
            ]
        },
        {
            nodeId: '4', nodeText: 'Videos', nodeIcon: 'folder',
            nodeChild: [
                { nodeId: '41', nodeText: 'Angular tutorials.mp4', nodeIcon: 'video' },
                { nodeId: '42', nodeText: 'Basics of Programming.mp4', nodeIcon: 'video' }
            ]
        }
  ];

  public treeFields: Object = { 
    dataSource: this.treeData, 
    id: 'nodeId', 
    text: 'nodeText', 
    child: 'nodeChild',
    iconCss: 'nodeIcon'
  };

  constructor() { }

  ngOnInit() {

  }

}

Note: here the ViewEncapsulation set as None, since encapsulation is not applicable for dynamically created elements. Otherwise we need to put our custom styles understyles.css file.

An element is created for each node with the mentionediconCss class, so we can apply our styling for that node there. You can apply the following styles in the home.component.css file.

.e-treeview {
    border: 1px solid #ccc;
    width: 400px;
}
.e-treeview .e-list-icon {
    background-repeat: no-repeat;
    background-image: url('https://ej2.syncfusion.com/angular/demos/src/images/icons/file_icons.png');
    height: 20px;
}
.e-treeview .e-list-icon.folder { background-position: -10px -552px }
.e-treeview .e-list-icon.docx { background-position: -10px -20px }
.e-treeview .e-list-icon.ppt { background-position: -10px -48px }
.e-treeview .e-list-icon.pdf { background-position: -10px -104px }
.e-treeview .e-list-icon.zip { background-position: -10px -188px }
.e-treeview .e-list-icon.audio { background-position: -10px -244px }
.e-treeview .e-list-icon.video { background-position: -10px -272px }
.e-treeview .e-list-icon.exe { background-position: -10px -412px }

Now the tree view appearance will be changed.


Drag and drop

Another important option for tree view is node drag and drop. This allows the user to reorder the nodes through UI interaction.

We can enable the drag-and-drop option by setting the allowDragAndDrop property.

<ejs-treeview id="myTree" [fields]="treeFields" [allowDragAndDrop]="true"></ejs-treeview>

This behavior can be customized to prevent dropping into any nodes. This was widely used in applications similar to file manager where the drop can’t be allowed into the file-type nodes.

This can be achieved through the nodeDragging and nodeDragStop event.

<ejs-treeview id="myTree" [fields]="treeFields" [allowDragAndDrop]="true" 
	(nodeDragging)="onNodeDragging($event)" (nodeDragStop)="onNodeDragStop($event)"></ejs-treeview>

Apply the conditions in the corresponding event handler.

public onNodeDragging (e) {
    if(e.droppedNode && e.droppedNode.querySelector('.folder') == null) {
        // to show the node drop not allowed icon
        var dragItemIcon = document.querySelector(".e-treeview.e-drag-item .e-icon-expandable");
        dragItemIcon.classList.add('e-no-drop');
    }
}

public onNodeDragStop (e) {
    if(e.droppedNode.querySelector('.folder') == null) {
        // to prevent the node drop action
        e.cancel = true;
    }
}

Now you can see the tree view with drag and drop enabled, where you are not allowed to drop any files or folders under the file node.

Node editing

Node editing is also an often-used feature that allows the user to rename the tree node dynamically through UI interaction. This is also a common and useful option in applications similar to file manager.

We can enable the node editing option by setting the allowEditing property.

<ejs-treeview id="myTree" [fields]="treeFields" [allowEditing]="true"></ejs-treeview>

Now you can edit the tree nodes by double-clicking on them, or by pressing F2 key from the keyboard.


Template

The tree nodes can be templated using the built-in template support. This is a great option to give the tree view a great look and feel.

Depending on the application scenario, we can customize the tree nodes with images, multiple elements, and so on. Here, we can form a template for our file manager scenario to represent the child item count in the parent element.

First, we will update the data for the root elements to show the child count.

public treeData: Object[] = [
	{
		nodeId: '03', nodeText: 'Documents', nodeIcon: 'folder', childCount: 2,
		...
	},
	{
		nodeId: '05', nodeText: 'Downloads', nodeIcon: 'folder', expanded: true, childCount: 4,
		...
	},
	{
		nodeId: '01', nodeText: 'Music', nodeIcon: 'folder', childCount: 1,
		...
	},
	{
		nodeId: '02', nodeText: 'Videos', nodeIcon: 'folder', childCount: 2,
		...
	}
];

Then we can form the tree node element structure based on the childCount attribute.

<ejs-treeview id="myTree" [fields]="treeFields"><ng-template #nodeTemplate let-data><div>
            {{data.nodeText}}<span *ngIf="data.childCount" class="files-count">
                ({{data.childCount}} files)</span></div></ng-template></ejs-treeview>

Now add your custom styles for your template in home.component.css.

.files-count {
    font-size: 9px;
    color: red;
}

Finally, the tree view becomes like the following image.


Summary

Overall, the tree view component was designed to be completely customizable, as well as have flexible usage from the application point of view.

If you would like to try the tree view component, you can download our free trial. You can visit the tree view source in GitHub and you can check our sample browser and documentation for detailed explanation and the understanding to proceed further.

If you have any questions or need any clarifications, please let us know in the comments section below. You can also contact us through our support forum or Direct-Trac. We are always happy to assist you!


Interview with HoloLens Succinctly Author Lars Klint

$
0
0

The following is a short interview with Succinctly series author Lars Klint, whose book HoloLens Succinctly was published on Monday, May 21. You can download the book here.

 

What should people know about the HoloLens? Why is it important?

HoloLens is currently the only available mixed reality device that offers detailed spatial mapping, allowing users to place and interact with holograms in the real world. It is the first step towards immersive mixed reality that actually works!

When did you first become interested in the HoloLens and digital reality?

I remember vividly seeing the announcement and reveal at the Windows 10 event in January 2015 and immediately being hooked. I signed up to get invited to spend $3,000 USD as soon as I could, and I even did my first international talk on HoloLens development before I even got a HoloLens myself.

By writing HoloLens Succinctly, did you learn anything new yourself?

I learned new details about managing all the various factors that influence the experience on the HoloLens. Colored light and curved walls for example can be problematic for the device to map properly in 3D. I also learned that writing a book is hard work!


Lars Klint

How will the HoloLens and digital reality change over the next few years?

Over the next few years, devices that map your real world will be more common, cheaper, and more accurate. Digital realities will become a generally accepted part of everyday life through mobile devices and wearables. Consumers will accept augmented reality experiences as part of well-known apps, such as Amazon shopping in 3D, or measuring your living room as a 3D model.

Do you see digital reality as part of a larger trend in software development?

Digital reality will become a more integral part of software development projects, but considering much of software development is “faceless,” it will continue to be more of a niche and included in specific projects. Having said that, programming for 3D experiences will become more prominent.

What other books or resources on HoloLens or digital reality do you recommend?

The best way to get involved in the HoloLens community and learn from other developers is to join the open Slack team at holodevelopersslack.azurewebsites.net. You can also read the great book Beginning Windows Mixed Reality Programming: For HoloLens and Mixed Reality Headsets by Sean Ong.

Perform Incremental Fetch Operations Using the Syncfusion Data Integration Platform

$
0
0

In almost all data warehousing scenarios, a common use case is to extract, move, or duplicate data from source RDBMS and to store them in some other target database or storage system for future analysis. When it comes to loading this data from source RDBMS to target, you have two methods.

  • Full Load - Will move all the rows from source RDBMS to target table even thogh you have already processed them before.
  • Incremental Fetch - Will fetch only the records which are not processed already and move them into target system. You are going to use the QueryDatabaseTableprocessor to bring the data incrementally from source table.

In this blog, you will see how to perform an incremental fetch operation using the “QueryDataBaseTable” processor in the Syncfusion Data Integration Platform. That is, you will learn how to fetch a newly added or modified record from a source table or data store and move it to a target table or data store.

Set up an environment

Install Syncfusion Data Integration Platform in your system.

Template

Download and extract the pre-defined template from this link and follow the steps below to upload the template (xml file) into the Data Integration Platform.

1. From the templates tab, click on the Upload button.


Figure 1: Upload template.

2. Choose the downloaded template file (IncrementalUpdateusingQueryDataBase.XML)  and upload it. Once the upload successful, you can find the template in the templates list.

Figure 2: View template in toolbar.

3. Now drag and drop the template into the data integration work area. You can see the data flow in the application as follows.

Figure 3: Overview.

You must have Microsoft SQL Server and the following table.

Source Table:InvestmentDetails– sample data.

NameIdInvestedAmountLastModified
Carla Adams15$553/8/2018 10:00
James Aguilar44$702/25/2018 13:35
Lili Alameda16$182/23/2018 15:00
Milton Albury6$7002/19/2018 12:28
Paul Alcorn5$2502/2/2018 9:05
Amy Alberts74$7801/17/2018 11:50
Kim Akers93$6201/08/2018 14:42


Figure 4: Source table

Now, you are going to incrementally fetch and move the data to the target table named UpdatedInvestments.

List of processors used in this sample

ProcessorComments
QueryDatabaseTableChecks for updated or newly added values and return the data from source table in AVRO format.
ConvertAvroToJSONConverts the incoming AVRO data into JSON data.
ConvertJSONToSQLConverts the incoming JSON data into SQL statements (insert/update query).
PutSQLExecutes the SQL statements.

Configure and enable SQL controller service

1. Select the processor group and click on the configuration icon from the operate panel.

Figure 5: Open configuration.

2. Go to the controller services tab.

Figure 6: Choose controller service

3. Enter the details for the below highlighted properties and enable the controller service.

Figure 7: Edit SQL Server configuration.

Figure 8: Enable the controller Service.

To learn more about controller services, refer here.

QueryDatabaseTable Processor

You must use this processor to fetch the updated values from the given table based on the last modified date. Select the processor and double click to open a configuration dialog. Specify the below properties in the configuration.

Table Name: InvestmentDetails

Columns to Return: Leave empty. If no columns are specified, all the columns will be returned from the source table.

Maximum-value-columns:  LastModified


Figure 9: Configure source table details.

This processor will store the latest date value as the state value and filter the records based on the date stored. To view the state value, right-click on the processor and select view->state.

The component state dialog will appear and shows the last modified date with column name and table name as keys. To clear the state value, select the “Clear state” option.


Figure 10: View component state.

On running, this processor returns the output in AVRO format.


Figure 11:View AVRO data.

ConvertAvroToJSON processor

Next, you have to use ConvertAvroToJSON processor to convert the incoming AVRO data into JSON format.

Under properties, set the JSON container options to “array.” AVRO data will be converted to an array of JSON objects.


Figure 12: Convert AVRO data into JSON data.

You can see the JSON output in the following screenshot.


Figure 13: View JSON data

ConvertJSONToSQL processor

You must convert the JSON input into relevant SQL Insert statements. For this operation, you need to use the ConvertJSONToSQL processor.

Under properties, set the statement type as either “INSERT” or “UPDATE,” and enter the target table name as “UpdatedInvestments” in the Table Name property.


Figure 14: Configure target table details.

Under the output queue, you can see the SQL statements as in the following screenshot.


Figure 15: View generated SQL query.

PutSQL processor

This processor is used to execute the incoming SQL statement. Just point out the relevant connection pool.


Figure 16: Choose SQL Server.

Now your data flow is ready.

Processor scheduling

You must schedule the overall dataflow to run periodically and move the data from source to destination.

Open configuration dialog for the “UpdateDatabaseTable” processor, move to the scheduling tab, choose the “timer driven” option, and set it for one minute. This will ensure that the data flow is run every minute, checking for new and updated records and moving them from the source to the destination.


Figure 17: Schedule data flow.

Please refer to the link below to learn more about scheduling:

https://help.syncfusion.com/data-integration/user-guide#scheduling-tab

Now, start all processors by clicking “start” button under the operate menu.


Figure 18: Execute the data flow.

If any values are inserted or updated (along with the LastModified date field) in the source table, they will be automatically moved to the target table as per the dataflow schedule.

You can try directly editing the source table along with the last modified column in the SQL server to see if the records are updated correctly.

Target table: UpdatedInvestments


Figure 19: Target table.

Conclusion

Hopefully this blog has shown you the steps involved in how to fetch data incrementally from source SQL tables and move it to a target SQL table using the QueryDataBaseTable processor in the Syncfusion Data Integration Platform. This dataflow will be very helpful when you want to perform data migration, data synchronization, and data transformation use cases between SQL tables.

If you are new to the Data Integration Platform, it is highly recommended that you follow our Getting Started guide.

If you’re already a Syncfusion user, you can download the product setup here. If you’re not yet a Syncfusion user, you can download a free, 30-day trial here.

If you have any questions or require clarification about this feature, please let us know in the comments below. You can also contact us through our support forum or Direct-Trac. We are happy to assist you!



Advantages of Syncfusion List View Over Xamarin List View

$
0
0

Syncfusion’s Xamarin.Forms list view component is used to display a list of data in a predefined or customized view. It offers high performance when bound with commonly used data sources. Data can be grouped, sorted, and filtered with ease. Key features include different layouts, item templating, swiping, horizontal orientation, item drag and drop, sticky headers and footers, and selection with different modes and gestures.


This blog post will explore the advantages of the Syncfusion list view component over the Xamarin.Forms framework list view, and then show how easy it is to get started with the Syncfusion list view.

Advantages of Syncfusion list view over Xamarin list view

The Syncfusion list view will make your development easier with its rich set of features and functionalities. The following are some feature advantages the Syncfusion list view has over the Xamarin.Forms framework list view.

  • Grouping: Group list items by setting the GroupDescriptor property in one line of code without having to make any changes in your ViewModel.


  • Swiping: Swipe list items left or right. The swipe views can be customized to be associated with custom actions.

  • Grid layout: Display list data in a predefined number of columns. ­This allows items to be displayed in a single column on smaller screens, or multiple columns on wider screens. 

  • Horizontal orientation: Display list items vertically or horizontally. In a horizontal orientation, items are arranged horizontally and can be scrolled horizontally. 
  • Filtering: Filter list items and display only those users need. Dynamic filtering is also supported. 
  • Sorting: Display list items in either ascending or descending order. Also allows items to be sorted with custom logic. 
  • Multiselection: Select more than one item in the list simultaneously. Different selection modes and selection gestures are also supported. The appearance of selected items can be customized easily.

  • Load more: Load more data at run time automatically or manually when reaching the end of the list. This feature helps improve the initial loading speed by minimizing data. Also, the loading indicator and load more button can be customized.
  • Built-in row drag and drop: Reorder list items by dragging them either with a long press or through a drag indicator view. The drag appearance of an item can be customized. 
  • Paging: List view items can be arranged across pages using the data pager control, which helps when interactively manipulating the data. 

  • Sticky header and footer: Header and footer items can be added to the list view. They can be frozen in place or scroll with the view. The Syncfusion list view also supports sticky group headers, where you can freeze a group header in the view until its items are scrolled out of view.

Besides these, the Syncfusion list view component for Xamarin.Forms supports all the other features in the Xamarin.Forms framework list view, such as grouping, autofitting items, pull to refresh, data binding to various item sources, custom sorting, custom grouping, item size customization, and more. 

Getting Started with Syncfusion List View

Next, we will take a quick look at getting started with the Syncfusion list view component for Xamarin.Forms and walk through the process of creating a real-world scenario for it. These are the steps to get started:

  • Configure the list view.
  • Configure the list view with data.
  • Define item templates.

Configuring the list view

NuGet package

First, create a Xamarin.Forms project and add the Syncfusion.Xamarin.SfListView NuGet package to the solution to install the necessary package and renderer assemblies for each platform.

Creating a cross-platform app

Step 1

Create a new cross-platform project as follows:

  • Open Visual Studio.
  • Choose Create New Project.
  • Select Templates > Visual C# > Cross-Platform > Cross Platform App (Xamarin).
  • Provide a project Name and project Location.
  • Click OK.

Step 2

A new window will appear. Here, select the Blank App template, the Xamarin.Forms option under UI Technology, and Portable Class Library (PCL) under Code Sharing Strategy.


Step 3

After creating the project, we need to add the NuGet packages. Right-click the project name in Solution Explorer and select Manage NuGet Packages. Search for Syncfusion.Xamarin.SfListView, and then install it.


Creating the list view

The list view component is entirely configurable in both XAML and code behind. Import the SfListView control namespace in your XAML page and add the SfListView control to the ContentPage or as a nested child based on your requirements.

<?xml
version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:syncfusion="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms"
             xmlns:local="clr-namespace:SfListViewApp"
             x:Class=" SfListViewApp.MainPage">                                                                                                                                             
  
        <syncfusion:SfListView x:Name="listView" />
   
</ContentPage>

Launching the list view on each platform

In Android, the list view will be launched without any further initialization. An additional step is required for launching the list view in iOS and UWP.

iOS project

After the Xamarin.Forms framework initializes and before LoadApplication is called, call the SfListViewRenderer.Init() method in the FinishedLaunching overridden method of the AppDelegate class, as demonstrated in the following code example.

publicoverridebool FinishedLaunching(UIApplication
app, NSDictionary options)
{
   ...
    Xamarin.Forms.Forms.Init();
    Syncfusion.ListView.XForms.iOS.SfListViewRenderer.Init();
    LoadApplication(newApp());
   ...
}

UWP project

Call the SfListViewRenderer.Init() method in the MainPageconstructor before LoadApplication is called, as demonstrated in the following code example.

public MainPage()
{
    ...
    Syncfusion.ListView.XForms.UWP.SfListViewRenderer.Init();
    LoadApplication(new App());
    ...
}

For UWP, one additional step is required if the project is built in release mode with the .NET Native tool chain enabled because reflection is used internally for sorting, grouping, and filtering features in the DataSource class. However, the issue can be solved at the application level by adding the following directives in the Default.rd.xml file in the application of the UWP project.

<Directivesxmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
  <LibraryName="Syncfusion.DataSource.Portable">
    <TypeName="System.Linq.EnumerableExecutor{System.Int32}"Dynamic="Required Public" />
    <TypeName="System.Collections.ObjectModel.ObservableCollection{}"Dynamic="Required Public" />
    <NamespaceName="System.Linq"Dynamic="Required All" />
  </Library>
</Directives>


Configuring list view with data

List view is a data-bound control. Therefore, you must create a data model to bind to it. 

In our example, a simple shopping category has been modeled that generates a list of shopping categories with a description and image for each category. In a real-world scenario, you can also bind the data from services and databases to render the list view based on your requirements.

Model class with properties

publicclassListViewShoppingCategoryInfo: INotifyPropertyChanged 
{
    privatestring categoryName;
    privatestring categoryDesc;
    private ImageSource categoryImage;
 
    publicstring CategoryName
    {
        get { return categoryName; }
        set
        {
            categoryName = value;
            OnPropertyChanged("CategoryName");
        }
    }
 
    publicstring CategoryDescription
    {
        get { return categoryDesc; }
        set
        {
            categoryDesc = value;
            OnPropertyChanged("CategoryDescription");
        }
    }
 
    public ImageSource CategoryImage
    {
        get { return categoryImage; }
        set
        {
            categoryImage = value;
            OnPropertyChanged("CategoryImage");
        }
    }
 
    publicevent PropertyChangedEventHandler PropertyChanged;
 
    privatevoid OnPropertyChanged(string name)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this,new PropertyChangedEventArgs(name));
    }
}
Populating the model collection

publicclassShoppingCategoryInfoRepository
{
    internal ObservableCollection<ListViewShoppingCategoryInfo> GetCategoryInfo()
    {
        var categoryInfo = new ObservableCollection<ListViewShoppingCategoryInfo>();
 
        for (int i = 0; i < CategoryNames.Count(); i++)
        {
            var info = new ListViewShoppingCategoryInfo()
            {
                CategoryName = CategoryNames[i],
                CategoryDescription = CategoryDescriptions[i],
                CategoryImage = ImageSource.FromResource("SfListViewApp.Icons." + CategoryNames[i] + ".jpg")
            };
            categoryInfo.Add(info);
        }
        return categoryInfo;
    }
 
    string[] CategoryNames = newstring[]    {
        "Fashion",
        "Electronics",
        "Home & Kitchen",
        "Sports & Health",
        "Kids",
        "Books",
        "Footwear",
        "Mobile & Accessories",
        "Flower Gift Cakes",
        "Watches",
        "Jewelry",
        "Food",
        "Perfumes",
        "Movies & Music",
        "Cameras& Optics"
    };
 
    string[] CategoryDescriptions = newstring[]    {
        "Latest fashion trends in online shopping for branded Shoes, Clothing, Dresses, Handbags, Watches, and Home Decor for Men& Women...",
        "Shop variety of electronics like Mobiles, Laptops, Tablets, Cameras, Gaming Consoles, TVs, LEDs, Music Systems, and much more...",
        "Purchase home & kitchen accessories like Cookware, Home Cleaning, Furniture, Dining Accessories, Showcase accessories, etc...",
        "Buy accessories for Badminton, Cricket, Football, Swimming, Sports shoes, Tennis, Gym, Volleyball, and Hockey at the lowest price...",
        "Shop for clothing for boys, girls, and babies. Explore the range of Tops, Tees, Jeans, Shirts, Trousers, Skirts, Body Suits...",
        "Purchase books across various categories at the lowest price. Read books online and download as PDF...",
        "Buy Footwear for Men, Women, and Kids, including Formal Shoes, Slippers, Casual Shoes, Sandals, and more at the best price...",
        "Buy branded Mobile Phones, Smartphones, Tablets, and Mobile Accessories like Headsets, Memory Cards, Chargers, Covers, etc...",
        "Buy different Flowers, Gifts, and Cakes online. Birthday Gifts, Anniversary Gifts, Mother’s Day Gifts, Flowers and Cakes etc...",
        "Latest range of trendy Digital Watches, Analog Watches, Digital Steel Watches, Digital LED Watches for Men and Women...",
        "Buy Jewelry for Men, Women, and Children from brands like Gitanjali, Tara, Orra, Sia Art Jewelry, Addons, Ayesha, Peora, etc...",
        "Shop from a wide range of best quality Fruits, Vegetables, Health Foods, Indian Grocery, Cereals, Noodles, Foods etc...",
        "Choose the best branded perfumes like Azzaro, Davidoff, CK, Axes, Good Morning, Hugo Boss, Jaguar, Calvin Klein, Antonio etc...",
        "Buy a variety of Movies & TV on Blu-ray in different languages, and Music in a variety of formats like audio CD, DVD, MP3, VCD, etc...",
        "Purchase a variety of cameras like Tamron, Sigma, Nikon, Sony, and Canon, and SLRs, Lenses, and Optics accessories at the best prices..."
    };
}

Configure the populated data or data from services or databases to a collection in the ViewModel. The collection can be any commonly preferred data source. I prefer ObservableCollection overall for its internal INotifyCollectionChanged implementation, as we generally expect the list view to be responsive. If collection changes are not a concern, then a generic List<T> can be used to hold the data, which is faster than the ObservableCollection.

publicclassListViewViewModel
{
    private ObservableCollection<ListViewShoppingCategoryInfo> categoryList;
 
    public ListViewViewModel()
    {
        GenerateSource();
    }
 
    public ObservableCollection<ListViewShoppingCategoryInfo> CategoryList
    {
        get { return categoryList; }
        set { this.categoryList = value; }
    }
 
    privatevoid GenerateSource()
    {
        ShoppingCategoryInfoRepository categoryinfo = new ShoppingCategoryInfoRepository();
        categoryList = categoryinfo.GetCategoryInfo();
    }
}
Binding data to list view

To bind the data source to the list view, set the view model as the binding context of the page and bind the collection containing the data in your view model to the SfListView.ItemsSource property as shown in the following example.

<?xml
version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:syncfusion="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms"
             xmlns:local="clr-namespace:SfListViewApp"
             x:Class=" SfListViewApp.MainPage">
                                                                                                                                             
    < ContentPage.BindingContext>
        <local:ListViewGettingStartedViewModel/>
    </ContentPage.BindingContext>
 
        <syncfusion:SfListView x:Name="listView" ItemsSource="{Binding CategoryList}"/>
   
</ContentPage>


Defining item templates 

By defining the SfListView.ItemTemplate of the list view, a custom user interface can be put in place to display the data items.

<syncfusion:SfListView x:Name="listView"
ItemsSource="{Binding CategoryList}"
                 ItemSize="160">
    <syncfusion:SfListView.ItemTemplate>
        <DataTemplate>
            <Frame BackgroundColor="White" Padding="1">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="0.35*"/>
                        <ColumnDefinition Width="0.65*"/>
                    </Grid.ColumnDefinitions>
                   
                    <Image Source="{Binding CategoryImage}"
                           HorizontalOptions="FillAndExpand"
                           VerticalOptions="FillAndExpand"/>
 
                    <Grid Grid.Column="1" Padding="10,0,0,0">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>
                       
                        <Label Text="{Binding CategoryName}" FontSize="Medium"
                               LineBreakMode="WordWrap" FontAttributes="Bold"/>
                       
                        <Label Grid.Row="1" Text="{Binding CategoryDescription}"
                               LineBreakMode="WordWrap" FontSize="Small" />
                    </Grid>
                </Grid>
            </Frame>
        </DataTemplate>
    </syncfusion:SfListView.ItemTemplate>
</syncfusion:SfListView>

This completes configuring a simple list view in an application. Running the sample after following the previous steps will render a shopping category list in your view as shown in the following screenshot. 


The complete sample can be downloaded here.

Summary

In this post, we have learned about creating and configuring the list view component with data, and the advantages of the Syncfusion list view component for Xamarin.Forms over the Xamarin.Forms framework list view. We hope you enjoyed the blog, and if you would like to try the list view component for yourself, download our trial setup, explore the demos for iOS and Android, and peruse the documentation. If you have any questions, you can post them in our community forums or in our Direct-Trac support system.

What’s New in 2018 Volume 2: Licensing Changes in the 16.2.0.x Version of Essential Studio

$
0
0

The 2018 Volume 2 release of Essential Studio not only includes a lot of exciting new features and improvements, but also some licensing-related changes that existing and evaluation customers should be aware of. In this blog post, we will summarize the list of licensing-related changes and the actions that customers have to take in order to resolve any issues that may arise.

Changes for current, paying customers

If you are a paying customer, and if you are not using NuGet packages, then these changes will not affect your upgrade in any way. You will be able to obtain the latest build from the “My Account>> License& Downloads” section of our website and install it as usual.

However, if you are using NuGet packages from either nuget.syncfusion.com or nuget.org, then you need to include a valid license key in your application code. This license key is different from the build unlock key and can be obtained from the “My Account >> License and downloads” section of our website. You must download the license key and register it in your code before initializing any Syncfusion controls. You can find more details in this help document.

Changes for current evaluators

If you are a current evaluator and would like to try our newest version, then you would also need to obtain and include a trial license key in your application project. This license file is different from the build unlock key and can be obtained from the “My Account >> Manage Trials” section of our website. You must download the license key and register it in your code before initializing any Syncfusion controls. You can find more details in this help document.

Transitioning from evaluator to customer

New customers can choose to uninstall the evaluation version of our product and then download and install the licensed version from the “My Account >> License and downloads” section of our website. You can also, alternatively, keep the same evaluation installation and just replace the trial license key with a paid license key. You can find more details in this help document.

Changes for nuget.org users without a Syncfusion account

 If you have directly obtained Syncfusion assemblies from nuget.org and don’t have a Syncfusion account, then you need to follow the steps below to obtain a free 30-day license key:

  • Register for a free Syncfusion account here.
  • Go to the start trials page and start a trial.
  • Finally, proceed to the Trial & Downloads section to obtain the license key.

Please try out the version 16.2 release and let us know if you run into any issues.

What’s New in 2018 Volume 2: Windows Forms Controls

$
0
0

We are pleased to announce new controls and features for Windows Forms released in the 2018 Volume 2. New combo box and list view controls have been added to the Windows Forms family, and the new data grid component is moved from preview to final. Let's look at a brief overview of the new controls and features.

New combo box control

The new combo box control provides support for editing, autocompletion, multiselection, and filtering features. It ships with built-in themes and support for complete UI customization.

combobox_multiSlection

New list view control

We developed a new lightweight list view control to help provide unmatched performance and its already used for our new combo box, and advanced filtering options for our new data grid component. The list view provides support for sorting, grouping, filtering, and complete UI customization along with built-in themes.
listview2

New data grid (final!)

With the 2018 Volume 2 release, the new Windows Forms data grid component is marked as final. Features include:
  • Master-details view to display nested tables.
  • Built-in busy indicators for long-running data operations when working with millions of records.
  • Cell merging support.
  • Font orientation support.
  • Office 2016 themes: white, black, grey, and colorful.
  • New combo box column type and multiselect filter row editor.
  • Further performance improvements in advanced filter UI and summary calculation.
You can find more details about all the features on this blog post.

Ribbon

Office 2016-style visual improvements

Our Windows Forms ribbon component already supports Office 2016 themes, so for this release we added Office 2016-style enhancements. Added features include:
  • Tab scrolling when there are more headers than space available.
  • Improved alignments and spacing for all the elements of ribbon tabs.
  • Support for adding ribbon backstage commands in the quick access toolbar (QAT).
  • Support for hiding the application icon.
  • Ribbon customization and quick access toolbar windows combined into single dialog similar to Office ribbons.

Calendar

UI customization improvements

The calendar control already provides support for customizing date cells. Now, the cells in year, decade, and century views can also be customized. Additionally, built-in tool tip and Office 2016 theme support has been added.
viewcustomization

Docking manager

Tab customization

The tab header appearance can be customized to various states via direct properties.
dockingmanager1

Syntax Editor

IntelliSence improvements

The IntelliSense pop-up appearance and end-user experience has been improved to be similar to the IntelliSense experience provided in Visual Studio. Office 2016 theme support has also been provided.
Intellisense

Multicolumn TreeView

Column autofit support

With the 2018 Volume 2 release, the column width of the multicolumn tree view control can be sized to fit its content. Support has also been provided for setting minimum and maximum widths.
MultiColumnTreeview Image (003)

Pivot Grid

Serialization and de-serialization

The pivot gird control provides support to serialize and de-serialize user settings with various customization options. You can find more details along with code samples on this blog post.

In addition to these new controls and features, we have included other minor improvements and bug fixes that you can check in the release notes. We hope that you will like these new features and we look forward to you to try them out in the 2018 Volume 2 release. You can find the 2018 Volume 2 Windows Forms install download link here. Please feel free to leave your feedback in the comments section below.

Viewing all 473 articles
Browse latest View live