ActiveReports 15 .NET Edition
ActiveReports 15 User Guide / Concepts / ActiveReports Web Designer / Integration to VueJS Application
In This Topic
    Integration to VueJS Application
    In This Topic

    This page explains how you can embed the ActiveReports Web Designer component in your VueJS application (ASP.NET Core). We will use React template to begin with and replace 'React front-end' application with the 'Vue.js front-end' application. To run the Vue Application Server, you will require the node.js JavaScript runtime and Vue CLI. Use the following command in the terminal or command prompt to install the Vue CLI:

    npm install -g @vue/cli

    1. Open Microsoft Visual Studio 2019 and create a new ASP .NET Core Web Application project.

      Create a New Project Dialog

    2. Type a name for your project and click Create.

      Configure your New Project Dialog

    3. Select ASP.NET Core 5.0 and choose the React.js project template from the dialog.

      Create a New Project Dialog

    4. Create a new ASP.NET Core Web Application project with the React template.

    5. Right-click the project in the Solution Explorer and select Manage Nuget Packages.

    6. Add the following packages to the project.

      GrapeCity.ActiveReports.Aspnetcore.Designer
      GrapeCity.ActiveReports.Aspnetcore.Viewer

    7. Add a new folder called 'resources' in application's root and place the report you want to display in the viewer, in this folder. The report you create in Web Designer, on saving, is saved at this location.

    8. Open 'Startup.cs' file and add the following 'using' statements at the top.

      using GrapeCity.ActiveReports.Aspnetcore.Viewer;
      using GrapeCity.ActiveReports.Aspnetcore.Designer;

    9. Add the following global variable in the 'Startup.cs' file:

      Startup.cs
      Copy Code
         //resources(reports, themes, images) location
         private static readonly DirectoryInfo ResourcesRootDirectory = new DirectoryInfo(".\\resources\\");
      
    10. Then, add the following code snippet in the ConfigureServices method of the 'Startup.cs' file:

      Startup.cs
      Copy Code
         services
           .AddReporting()
           .AddDesigner()
           .AddMvc(options => options.EnableEndpointRouting = false)
           .AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
      
    11. Similarly, add the following code snippet in the Configure method of the 'Startup.cs' file:

      Startup.cs
      Copy Code
         app.UseReporting(config => config.UseFileStore(ResourcesRootDirectory));
         app.UseDesigner(config => config.UseFileStore(ResourcesRootDirectory, false));
      

      Since ASP.NET Core does not provide an in-built template and development server for VueJS, we'll add a static class to launch the Vue Development Server along with the ASP.NET Core Server.
    12. In the Solution Explorer, right-click the Solution and add a new class with the name 'VueHelper.cs'.

    13. Replace the content of the 'VueHelper.cs' file with the following code.

      VueHelper.cs
      Copy Code
      using Microsoft.AspNetCore.Builder;
      using Microsoft.AspNetCore.SpaServices;
      using Microsoft.Extensions.DependencyInjection;
      using Microsoft.Extensions.Logging;
      using System;
      using System.Diagnostics;
      using System.IO;
      using System.Linq;
      using System.Net.NetworkInformation;
      using System.Runtime.InteropServices;
      using System.Threading.Tasks;
      namespace WebDesigner_VueJS
      {
          public static class VueHelper
          {
              // default port number of 'npm run serve'
              private static int Port { get; } = 8080;
              private static Uri DevelopmentServerEndpoint { get; } = new Uri($"http://localhost:{Port}");
              private static TimeSpan Timeout { get; } = TimeSpan.FromSeconds(30);
              // done message of 'npm run serve' command.
              private static string DoneMessage { get; } = "DONE  Compiled successfully in";
              public static void UseVueDevelopmentServer(this ISpaBuilder spa)
              {
                  spa.UseProxyToSpaDevelopmentServer(async () =>
                  {
                      var loggerFactory = spa.ApplicationBuilder.ApplicationServices.GetService<ILoggerFactory>();
                      var logger = loggerFactory.CreateLogger("Vue");
                      // if 'npm run serve' command was executed yourself, then just return the endpoint.
                      if (IsRunning())
                      {
                          return DevelopmentServerEndpoint;
                      }
                      // launch vue.js development server
                      var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
                      var processInfo = new ProcessStartInfo
                      {
                          FileName = isWindows ? "cmd" : "npm",
                          Arguments = $"{(isWindows ? "/c npm " : "")}run serve",
                          WorkingDirectory = "ClientApp",
                          RedirectStandardError = true,
                          RedirectStandardInput = true,
                          RedirectStandardOutput = true,
                          UseShellExecute = false,
                      };
                      var process = Process.Start(processInfo);
                      var tcs = new TaskCompletionSource<int>();
                      _ = Task.Run(() =>
                      {
                          try
                          {
                              string line;
                              while ((line = process.StandardOutput.ReadLine()) != null)
                              {
                                  logger.LogInformation(line);
                                  if (!tcs.Task.IsCompleted && line.Contains(DoneMessage))
                                  {
                                      tcs.SetResult(1);
                                  }
                              }
                          }
                          catch (EndOfStreamException ex)
                          {
                              logger.LogError(ex.ToString());
                              tcs.SetException(new InvalidOperationException("'npm run serve' failed.", ex));
                          }
                      });
                      _ = Task.Run(() =>
                      {
                          try
                          {
                              string line;
                              while ((line = process.StandardError.ReadLine()) != null)
                              {
                                  logger.LogError(line);
                              }
                          }
                          catch (EndOfStreamException ex)
                          {
                              logger.LogError(ex.ToString());
                              tcs.SetException(new InvalidOperationException("'npm run serve' failed.", ex));
                          }
                      });
                      var timeout = Task.Delay(Timeout);
                      if (await Task.WhenAny(timeout, tcs.Task) == timeout)
                      {
                          throw new TimeoutException();
                      }
                      return DevelopmentServerEndpoint;
                  });
              }
              private static bool IsRunning() => IPGlobalProperties.GetIPGlobalProperties()
                      .GetActiveTcpListeners()
                      .Select(x => x.Port)
                      .Contains(Port);
          }
      }
      
    14. Again, open the 'Startup.cs' file  and modify the app.UseSpa method (inside Configure method) with the following code.

      Startup.cs
      Copy Code
      app.UseSpa(spa =>
          {
              spa.Options.SourcePath = "ClientApp";
              if (env.IsDevelopment())
              {           
                  // Launch development server for Vue.js
                  spa.UseVueDevelopmentServer();
              }
          });
      
    15. Add web.config file in the application's root with the following content:

      web.config
      Copy Code
      <configuration>
          <system.webServer>
            <security>
              <requestFiltering allowDoubleEscaping="true"/>
            </security>
          </system.webServer>
        </configuration>
      

      Configure VueJS front end

    16. Remove the existing ClientApp folder.

    17. Open the project root in the run command prompt or terminal window and run the following command:

      vue create client-app

      (The Vue CLI does not allow upper case letters in project names).
    18. Once the Vue CLI finishes generating the project, rename the client-app folder to ClientApp

      With above three steps, we have fully replaced the 'React front-end' application with the 'Vue.js front-end' application.  

    19. Expand the ClientApp folder.

    20. Open 'package.json' file and add the following packages for ActiveReports' Viewer and Designer under 'dependencies':

      "@grapecity/ar-designer": "latest",
      "@grapecity/ar-viewer": "latest",

    21. Then, add the following package under the "devDependencies" in 'package.json' file:

      "ncp": "^2.0.0",

    22. Replace the 'scripts' section in 'package.json' file with the following content:

      package.json
      Copy Code
         "scripts": { 
            "deploy-bundles": "ncp ./node_modules/@grapecity/ar-viewer/dist ../wwwroot/assets && ncp ./node_modules/@grapecity/ar-designer/dist ../wwwroot/assets",  
            "serve": "npm run deploy-bundles && vue-cli-service serve",  
            "build": "npm run deploy-bundles && vue-cli-service build",  
            "lint": "vue-cli-service lint"
         },
      
    23. Open ClientApp folder in the command prompt or terminal window and run the following command to install the npm packages.

      npm install

    24. Open 'App.vue' inside the ClientApp\src folder and replace its default content with the following code.

      App.vue
      Copy Code
      <template>
          <div id="designer-id" style="width: 100%; height: 100%;"></div>
      </template>
      <script>
          var viewer = null;
          var id = null;
          export default {
              name: 'App',
              mounted() {
                  const designerOptions = window.GrapeCity.ActiveReports.WebDesigner.createDesignerOptions();         
                  designerOptions.reportInfo = id ? { id: id, name: id } : null;
                  designerOptions.reportItemsFeatures.table.autoFillFooter = true;
                  designerOptions.openButton.visible = true;
                  designerOptions.saveButton.visible = true;
                  designerOptions.saveAsButton.visible = true;
                  designerOptions.documentation.home = 'https://www.grapecity.com/activereports/docs/v15/online-webdesigner/overview.html';
                  designerOptions.openViewer = this.openViewer;
                  designerOptions.dataTab.dataSets.canModify = true;
                  designerOptions.dataTab.dataSources.canModify = true;
                  window.GrapeCity.ActiveReports.WebDesigner.renderApplication('designer-id', designerOptions);
              },
              methods: {
                  openViewer: function (options) {
                      if (viewer) {
                          viewer.openReport(options.reportInfo.id);
                          return;
                      }
                      viewer = window.GrapeCity.ActiveReports.JSViewer.create({
                          locale: options.locale,
                          element: '#' + options.element,
                          reportService: {
                              url: 'api/reporting',
                          },
                          reportID: options.reportInfo.id,
                          settings: {
                              zoomType: 'FitPage'
                          },
                      });
                  },
                  closeViewer : function() {
                      this.viewerElement.nativeElement.firstElementChild.remove();
                  }
              }
          }
      </script>
      
    25. Modify the content for the 'index.html' inside the ClientApp\public folder as follows:

      index.html
      Copy Code
      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="utf-8">
          <meta http-equiv="X-UA-Compatible" content="IE=edge">
          <meta name="viewport" content="width=device-width,initial-scale=1.0">
          <link rel="icon" href="<%= BASE_URL %>favicon.ico">
          <link rel="stylesheet" href="assets/vendor/css/bootstrap.min.css" />
          <link rel="stylesheet" href="assets/vendor/css/fonts-googleapis.css" type="text/css" />
          <link rel="stylesheet" href="assets/jsViewer.min.css" />
          <link rel="stylesheet" href="assets/web-designer.css" />
          <title>WebDesigner VueJS</title>
      </head>
      <body>                    
          <script src="assets/jsViewer.min.js"></script>
          <script src="assets/web-designer.js"></script>
          <div id="app"></div>
          <!-- built files will be auto injected -->
      </body>
      </html>
      
    26. Press Ctrl + Shift + B to build your project and then press F5 to run it.