6

I have bootstrapped Angular with a ASP.NET MVC app. How do I conditionally load the MVC bundles based on what Angular view is getting rendered.

Index.cshtml

<!DOCTYPE html>

<html ng-app="maypp">
<body>

    <div class="container">

        @*HEADER*@
        <div header></div>


        <div ui-view></div>

        @*FOOTER*@
        <div footer></div>

    </div>
    @Scripts.Render("~/bundles/bundle1")
    @Scripts.Render("~/bundles/bundle2")

</body>
</html>

I need to load bundle1 for Angular view 1 only. Other views need to include both bundle1 and bundle2. I am using AngularJS, not Angular 2. Any response is appreciated.

DotnetDude
  • 11,617
  • 35
  • 100
  • 158
  • Possible duplicate of [How to load external scripts dynamically in Angular?](https://stackoverflow.com/questions/34489916/how-to-load-external-scripts-dynamically-in-angular) – CodeCaster Jun 11 '18 at 21:17
  • See also [Is there an easy way to render absolute URLs with Microsoft Web Optimization framework / script bundling?](https://stackoverflow.com/questions/21731577/is-there-an-easy-way-to-render-absolute-urls-with-microsoft-web-optimization-fra). – CodeCaster Jun 11 '18 at 21:17
  • @CodeCaster That response is for Angular 2. I am using AngularJS in my app. – DotnetDude Jun 12 '18 at 02:50
  • You can apply the same principles explained there. – CodeCaster Jun 12 '18 at 05:10
  • I am neither using WebPack nor the System.JS. Not sure how that answer would translate to a AngularJS solution. – DotnetDude Jun 12 '18 at 14:59
  • 1
    Look Dude, in the end it comes down to appending a ` – CodeCaster Jun 12 '18 at 15:10
  • I'm not too familiar with Angular in general, but wouln't using two different `_Layout.cshtml` files with their respective bundles solve it for you? Then you'd import them at the beginning of each View. – Tiramonium Jun 21 '18 at 11:40

2 Answers2

0

You can put this in the bottom of your cshtml view. However, you might want replace random number checker with your business logic :)

Option 1:

@section Scripts {

    @if (new Random().Next(10) > 5)
    {
        @Scripts.Render("~/bundles/x")
    }
    else
    {
        @Scripts.Render("~/bundles/y")
    }

}

Option 2:

Bundle 1:

function startBundleOne(){
   //bundle logic
}

Bundle 2:

function startBundleTwo(){
   //bundle logic
}

AngularJS view:

if (something){
    startBundleOne();
} else {
    startBundleTwo();
}

Option 3:

var scriptPath;
    if (something){
        scriptPath = "pathA";
    } else {
        scriptPath = "pathB";
    }
var script = document.createElement('script');
script.setAttribute('src',scriptPath);
document.head.appendChild(script);
Daniël Camps
  • 1,737
  • 1
  • 22
  • 33
  • The business logic for the if condition is where I am stuck. I need to check that the view rendered by Angular is ViewA or not before loading the scripts. But the issue is that Angular is a client side rendering engine and the Index.cshtml is not reloaded when Angular loads a new view. – DotnetDude Jun 19 '18 at 14:15
  • Ok that's trickier. In that case you could load both budles, wrap your bundles each in a different global function without executing them, and call that global function from an angular script. – Daniël Camps Jun 19 '18 at 14:18
  • Can you elaborate more on how that can be accomplished? (with a sample) – DotnetDude Jun 19 '18 at 16:53
  • I added option 2 and option 3, both of these should work – Daniël Camps Jun 20 '18 at 08:49
0

You are using Angular UI Router, it will be easy that way. Create two separate states such as for bundle 1, app1 and for bundle 2, app2 as shown below:

$stateProvider
  .state('app1', {
    abstract: true,
    url: '/app1',
    template: '<div ui-view></div>'
});
$stateProvider
  .state('app2', {
    abstract: true,
    url: '/app2',
    template: '<div ui-view></div>'
})

After this use oclazyload library to load the bundles for different states as shown below:

$stateProvider
  .state('app1', {
    abstract: true,
    url: '/app1',
    template: '<div ui-view></div>',
    resolve: {
      plugins: ['$ocLazyLoad', function($ocLazyLoad) {
        return $ocLazyLoad.load([
          '~/bundles/bundle1.js'
        ]);
      }]
    }

});
$stateProvider
  .state('app2', {
    abstract: true,
    url: '/app2',
    template: '<div ui-view></div>',
    resolve: {
      plugins: ['$ocLazyLoad', function($ocLazyLoad) {
        return $ocLazyLoad.load([
          '~/bundles/bundle2.js'
        ]);
      }]
    }
})

Now you have two different states running with two different bundles. I have implemented this in one of my projects and it is working flawlessly.

Update:

angular
  .module('myApp')
  .config(['$stateProvider', function($stateProvider) {
    $stateProvider
      .state('app1', {
        abstract: true,
        url: '/app1',
        template: '<div ui-view></div>',
        resolve: {
          plugins: ['$ocLazyLoad', function($ocLazyLoad) {
            return $ocLazyLoad.load([
              '~/bundles/bundle1.js'
            ]);
          }]
        }

      })
      .state('app2', {
        abstract: true,
        url: '/app2',
        template: '<div ui-view></div>',
        resolve: {
          plugins: ['$ocLazyLoad', function($ocLazyLoad) {
            return $ocLazyLoad.load([
              '~/bundles/bundle2.js'
            ]);
          }]
        }
      })
  }])
Abhishek Singh
  • 2,642
  • 15
  • 24