Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to set AngularJS $provide.constant values from a C# MVC Model?

I have an AngularJS application with a .NET MVC/WebAPI backend. I have one MVC action that serves up my main HTML page that loads my AngularJS app. This MVC action loads several application settings from the Web.config as well as the database and returns them to the view as a model. I'm looking for a good way to set those MVC Model values as $provide.constant values in my AngularJS .config method.

MVC Controller method:

public ActionResult Index() {
    var model = new IndexViewModel {
        Uri1 = GetUri1(),
        Uri2 = GetUri2()
        //...etc
    };
    return View(model);
}

My MVC _Layout.cshtml:

@model IndexViewModel
<!doctype html>
<html data-ng-app='myApp'>
<head>
    @Styles.Render("~/content/css")
    <script type='text/javascript'>
        @if (Model != null)    //May be null on error page
        {
            <text>
                var modelExists = true;
                var uri1 = '@Model.Uri1';
                var uri2 = '@Model.Uri2';
            </text>
        }
        else
        {
            <text>
                var modelExists = false;
            </text>
        }
    </script>
</head>
<body>
    <!-- Body omitted -->
    @Scripts.Render("~/bundles/angular", "~/bundles/app") //Loads angular library and my application
</body>

app.js:

"use strict";
angular.module('myApp', [])
    .config(['$provide' '$window', function ($provide, $window) {
        if ($window.modelExists){
            $provide.constant('const_Uri1', $window.uri1);
            $provide.constant('const_URi2', $window.uri2);
        }            
    }]);

This is a vastly simplified version of my code but I think it illustrates my concern. Is there a better or standard way of doing this that I am overlooking? I don't like the code in my _Layout.cshtml because I have many more configuration values.

like image 496
Adam Modlin Avatar asked Jul 15 '14 15:07

Adam Modlin


People also ask

What is the correct way of defining the name of a constant file in AngularJS?

It is declare using "constant" keyword. As we define our app-keys in Web. Config file for ASP.NET application, which further we can use anywhere in the application, like wise same we can declare constant data in AngularJS globally that can be used throughout the application.

What is controllerAs in AngularJS?

In AngularJS, a Controller is defined by a JavaScript constructor function that is used to augment the AngularJS Scope. Controllers can be attached to the DOM in different ways.

What is Provider in AngularJS?

A provider is an object with a $get() method. The injector calls the $get method to create a new instance of a service. The Provider can have additional methods which would allow for configuration of the provider. AngularJS uses $provide to register new providers.

What is Factory in AngularJS?

What is Factory in AngularJS? Factory is an angular function which is used to return the values. A value on demand is created by the factory, whenever a service or controller needs it. Once the value is created, it is reused for all services and controllers. We can use the factory to create a service.


1 Answers

If you have a bunch of config values and you don't mind an extra network call, one way to do this is to create an MVC view that returns the settings as an Angular constant...

using System.Web.Script.Serialization;

// ...

public ActionResult Settings(string angularModuleName = "myApp")
{
    var settings = new 
    {
        uri1 = GetUri1(),
        uri2 = GetUri1()
        // ...
    };

    var serializer = new JavaScriptSerializer();
    var json = serializer.Serialize(settings);

    var settingsVm = new SettingsViewModel
    {
        SettingsJson = json,
        AngularModuleName = angularModuleName
    };

    Response.ContentType = "text/javascript";
    return View(settingsVm);
}

In the Razor view...

@model MyApp.SettingsViewModel
@{
    Layout = null;
}

(function (app) {
    app.constant('settings', @Html.Raw(Model.SettingsJson));
})(angular.module('@Model.AngularModuleName'));

In the pages that need the files, just add a script tag to bring in the constants...

@Scripts.Render("~/bundles/angular", "~/bundles/app") //Loads angular library and my application
<script src="/home/settings?appname=foo"></scripts>

This will return the script...

(function (app) {
    app.constant('settings', {
        "uri1": "https://uri1",
        "uri2": "https://uri2"
    });
})(angular.module('foo'));

Now you can inject the settings service anywhere in your Angular code. Nothing is leaked into the global scope.

You can also use this technique to inject the settings directly into a particular HTML view, but I generally prefer to split it out so that it is included only when needed.

like image 72
Anthony Chu Avatar answered Nov 03 '22 00:11

Anthony Chu