Support for AngularJS-Based Cordova Windows Apps


  • I am using Cordova 4.0.0 with AngularJS 1.2.26, UI-Bootstrap 0.11.2, and UI-Router 0.2.11 to create apps for Windows (8 and 8.1).

    Looking at the DOM inspector within Visual Studio, it seems that every node that has the ui-view directive is getting populated with its own set of head and body tags (which wraps around the template in question). I am having trouble pinning down where these extra nodes are being inserted, but it seems that the translation to a Windows app is the culprit, as the same code works as desired in the latest Chrome, FireFox, and IE desktop browsers, as well as within Android -- that is, no extra nodes are being inserted when content loads.

    Does anyone have any insight on this behavior? It might also be worthwhile to note that ngCsp is being used to alleviate dyanmic content insertion restrictions on Metro applications.

    • Edited by GrumpyMonk Thursday, November 6, 2014 9:03 PM
    Thursday, November 6, 2014 9:00 PM

All replies

  • Do you have some sample HTML & JavaScript to simulate the problem you are running into? If so, please post it here. That would be helpful to identify and isolate the exact problem you are running into.

    Windows Store Developer Solutions, follow us on Twitter: @WSDevSol|| Want more solutions? See our blog

    Friday, November 7, 2014 5:38 PM
  • Hi Prashant, thank you for replying. This code is for a customer's project, but the basic layout is as follows:

    HTML (index.html):

    <!doctype html>
    <html class="no-js" ng-csp>
      <meta charset="utf-8">
      <meta name="description" content="">
      <meta name="viewport" content="width=device-width">
      <link rel="stylesheet" href="styles/bootstrap.css" />
      <link rel="stylesheet" href="styles/fonts/font-awesome.css" />
      <link rel="stylesheet" href="styles/animate.css" />  
      <link rel="stylesheet" href="styles/angular/angular-csp.css" />
      <link rel="stylesheet" href="styles/main.css" />  
      <!--[if lt IE 7]>
        <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
      <div ui-view>
      <!--[if lt IE 9]>
      <script src="scripts/es5-shim.js"></script>
      <script src="scripts/json3.js"></script>
      <script src="scripts/winstore-jscompat.js"></script>  
      <script src="scripts/jquery.js"></script>
      <script src="scripts/angular.js"></script>
      <script src="scripts/angular-resource.js"></script>
      <script src="scripts/angular-cookies.js"></script>
      <script src="scripts/angular-sanitize.js"></script>
      <script src="scripts/angular-animate.js"></script>
      <script src="scripts/angular-touch.js"></script>
      <script src="scripts/angular-ui-router.js"></script>
      <script src="scripts/angular-base64.js"></script>
      <script src="scripts/ui-bootstrap-tpls.js"></script>
      <script src="scripts/prototypes.js"></script>
      <script src="scripts/app.js"></script>
      <script src="scripts/routes.js"></script>
      <script src="scripts/CordovaInit.js"></script>
      <script src="scripts/providers/SystemConfig.js"></script>
      <script src="scripts/providers/ApiHttpInterceptor.js"></script>
      <script src="scripts/services/ApiResource.js"></script>
      <script src="scripts/services/StorageService.js"></script>
      <script src="scripts/services/LoginService.js"></script>
      <script src="scripts/controllers/DialogController.js"></script>
      <script src="scripts/controllers/StartupController.js"></script>
      <script src="scripts/controllers/LoginController.js"></script>
      <script src="scripts/controllers/MainController.js"></script>
      <script src="scripts/controllers/NavController.js"></script>
      <script src="scripts/controllers/SystemController.js"></script>
      <script src="scripts/config.js"></script>
      <script src="cordova.js"></script>

    HTML (default.html):

    <div ui-view>
      <div class="row">
        <div class="col-md-7">
          <div class="panel panel-default">
            <div class="panel-heading text-center heading-with-icon">
              <i class="icon edit-icon"></i>
              <h3 class="panel-title">Choose Existing</h3>
            <div class="panel-body text-center">
              <div style="margin-bottom: 40px;">
                Begin typing the target's name and select from the dropdown list.
              <form role="form">
                <div class="form-group">
                  <input type="text" class="form-control" placeholder="Target Name" ng-model="target"
                    typeahead="name(t) for t in targets | filter: $viewValue | limitTo: 10"
                    typeahead-on-select="onTargetSelected($item, $model, $label)" />
        <div class="col-md-5">
          <div class="panel panel-default" sg-go-state="target.new">
            <div class="panel-heading text-center heading-with-icon">
              <i class="icon new-icon"></i>
              <h3 class="panel-title">Create a New Target</h3>
            <div class="panel-body text-center">
              Input information to create a new target.
          <div class="panel panel-default" ng-click="simulatedMode()">
            <div class="panel-heading text-center heading-with-icon">
              <i class="icon simulated-mode-icon"></i>
              <h3 class="panel-title">Simulated Mode</h3>
            <div class="panel-body text-center">
              Use device without target.

    There's nothing special in the JavaScript, as it should all be taken care of by the Angular routing. The routes are defined as follows:

    (function () {
      'use strict';
        .config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
          // For any unmatched url, redirect to /state1
          // Now set up the states
            .state('start', {
              url: '/start',
              templateUrl: 'views/startup.html',
              controller: 'StartupController'
            .state('login', {
              url: '/login',
              templateUrl: 'views/login.html',
              controller: 'LoginController'
            .state('main', {
              abstract: true,
              url: '/',
              templateUrl: 'views/main.html',
              controller: 'MainController'
            .state('default', {
              parent: 'main',
              url: 'patient',
              templateUrl: 'views/default.html',
              controller: 'DefaultController'

    With these two HTML pages, when routing occurs, "default.html" is inserted into "index.html" within the index.html's <div ui-view></div> tags. However, the insertion adds the extra head and body tags, with the content inside the extra <body></body> block. Very bizarre.


    Monday, November 10, 2014 1:54 PM
  • Please let me know if you find a solution for this. I'm having the same issue.
    Saturday, December 20, 2014 8:55 PM