Question

I've encountered what I believe to be a common scenario, in which I am using an MVC pattern (specifically ASP.NET's MVC framework) for a web application, with AngularJS on the front-end. My problem is that I have a particular value which is part of the model getting passed to my view, which I also want to make available to my Angular controller's $scope, ideally as soon as the controller is initialized.

How to do this is a question that has been asked and answered before. There's an obvious candidate for it: ngInit. However, at some point Angular updated their documentation with what appears to be a warning against this specific thought:

The only appropriate use of ngInit is for aliasing special properties of ngRepeat, as seen in the demo below. Besides this case, you should use controllers rather than ngInit to initialize values on a scope.

The suggested alternative isn't very relevant.

Of course, there are other workarounds I can think of. The view could insert the value into an ngModel directive on a hidden input, for example. Or I could just plain ignore the warning and use ngInit anyway. But any that I can think of are either an uglier way of doing the same thing as ngInit, or clearly worse.

Ultimately the fact that what seems like the obvious solution to me is apparently the wrong one is probably an indicator that my mindset isn't in tune with how Angular is supposed to be done. So my question isn't "how do I deal with this scenario", instead it's:

  1. How am I supposed to deal with, or avoid, this scenario?
  2. Why am I not supposed to use ngInit?

A clarification, since from the first two comments this isn't clear: This is for a situation where some or most of the page is being served directly as the MVC view, with only some particular piece of functionality being provided by Angular. The data that I want to pass to my Angular controller is already passed to the view in the model. I don't want the Angular controller to then go and have to do its own get request to the server just to get the same parameter that's already available to the view in a different format.

Was it helpful?

Solution

You should pass it from your server side controller to your AngularJS controller by using either a 'value' or 'constant' provider, as described here: https://docs.angularjs.org/guide/providers

For example, you could do something like the following:

<script>
    angular.module("hobbitModule").value("companionship", @Html.Raw(Model));
</script>

and then inject it in to your controller

var module = angular.module("hobbitModule");
module.controller("CompanionshipController", function($scope, companionship) {
    $scope.companions = companionship;
});

as described in this article: http://blog.mariusschulz.com/2014/03/25/bootstrapping-angularjs-applications-with-server-side-data-from-aspnet-mvc

If you think it may become more complicated that just a value, you could use a Service provider and inject that instead of the value provider.

OTHER TIPS

supposed that you have this model :
Model

public class Product
{
        public int Id { get; set; }
        public string Name { get; set; }
        public float Price { get; set; }
        public string Description { get; set; }
}

this way you can pass data from your controller into your view :
Controller

public string GetSerializedProduct()
{
    var products = new[] 
    { 
        new Product{Id=1,Name="product1",Price=4500,Description="description of this product"},
        new Product{Id=2,Name="product2",Price=500,Description="description of this product"},
        new Product{Id=3,Name="product3",Price=400,Description="description of this product"},
        new Product{Id=4,Name="product4",Price=5500,Description="description of this product"},
        new Product{Id=5,Name="product5",Price=66500,Description="description of this product"}
    };
    var settings = new JsonSerializerSettings { ContractResolver=new CamelCasePropertyNamesContractResolver()};
    return JsonConvert.SerializeObject(products,Formatting.None,settings);
    }
}

View :

@model string
<div class="container" ng-init="products = @Model">
    <div class="row">
        <div class="col-lg-12">
            <table class="table table-condensed table-hover">
                <tr>
                    <th>Id</th>
                    <th>Product Name</th>
                    <th>Price</th>
                    <th>Description</th>
                </tr>
                <tr ng-repeat="product in products">
                    <td>{{product.id}}</td>
                    <td>{{product.name}}</td>
                    <td>{{product.price}}</td>
                    <td>{{product.description}}</td>
                </tr>
            </table>
        </div>
    </div>
</div>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top