4

I'm starting to learn AngularJS and I'm trying to use it in a MVC application. I have an MVC ViewModel with properties which I've populated from the database and I have a view which is bound to this ViewModel. So in a normal MVC view I can do something like @Model.UserBaseViewModel.FirstName. What I'm trying to do is have my data come come from the ViewModel and also be saved through the ViewModel but I want AngularJS to do things like Editing and displaying the data like this:

CODE

app.controller('ConsultantPersonalInformationController', function($scope, $filter, $http) {
    $scope.user = {
        id: 1,
        firstName: @Model.UserBaseViewModel.FirstName,
        lastName: @Model.UserBaseViewModel.LastName
    };

    //other code is here
});

I'm not sure if there's a way to do do this. Does AngularJS need to get and save the data being displayed or can I use MVC ViewModel properties instead.

3 Answers 3

4

As you suspected, this is not the way to pull this off.

AngularJS has an SPA architecture, meaning you load your first page once and then you switch states without going to the server (except for fetching the template HTML if needed, or specified explicitly using an ajax request). Writing firstName: @Model.UserBaseViewModel.FirstName has no meaning since the @Model.. line is evaluated on the server side before the page is downloaded to the client, and since you're switching states constantly (or you can, anyway) the data is not availab le.

You need to switch to a RESTful state of mind, where you send requests to servers that return the data you need, and then you populate that data. So let's say that upon entry to state A you need to go and fetch user data, you'll have code similar to:

app.controller('ConsultantPersonalInformationController', function($scope, $filter, $http, userService) {

    userService.getUserData().then(function(res) { 
        $scope.user = {
            id: 1,
            firstName: res.FirstName,
            lastName: res.LastName
        };
    }

    //other code is here
});

getUserData is an async operation that will return a promise (read more here), and once ready, you'll have the server returned data in res variable which is the callback function.

Sign up to request clarification or add additional context in comments.

7 Comments

I agree using a service to call to retrieve the data is one approach. But, with MVC it is possible to bootstrap the page on load. This is nice to reduce to number of calls back to the server. So instead of loading the html and then making a second call back you can pass the model with the initial request. You can even use ng-init to load/display the data in the page if needed. The only thing to be cautious of is to ensure you don't pass an overly bloated model.
@rlcrews, while you're right that with MVC, you can write data directly to page, doing that with Angular, is not the Angular way. Angular is not a data binding library like Knockout, it is a full featured framework designed for single page application creation. Using a HTTP call to the server is the best approach to load data. NNassar would be better off creating a single page for the functionality he's wanting, loading, displaying and editing, and then doing get's and posts to move the data from the controller to his mvc endpoints.
@rlcrews In my app, I also get (very very minimal) all-states-relevant data on the first page if it's something that needs to be known throughout the entire SPA, but in this case I showed him the state of mind he wants to pursure for a certain page, and how most of his states should look like.
I really like your example, but I'd love to see it include a collection as well. I'm not sure how that would map out in angularJS.
@BrianLegg You would do it the same way. .then(function (res) { $scope.users = res; }); and then you do whatever you want with it.
|
0

You will need to pass the MVC model to the page first and insert it into a JS wrapper. From there you can then reference it within your controller. Just remember to have the JS wrapper in your page within the scope of your controller. Here is a quick example

From the MVC controller create some data and pass it as a model to the page

public ViewResult Index()
        {
            object model = bootStrapData();
            return View("Index", model);
        }

private string bootStrapData()
        {
            string someObject = string.Empty;
            var c = //dosomething
            someObject= c.ToString();

            //even though one value we will follow the Json pattern and camelCase the return
            var settings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };
            return JsonConvert.SerializeObject(isReportWriter, Formatting.None, settings);
        }

Within your view set the model to a javascript variable

<!-- Bootstrapping controller from ASP.MVC Controller-->
<script type="text/javascript">
    app.factory('bootStrappedData', function() {
        return   { someObject: @Html.Raw(Model) };
    });
</script>

Then within your controller you can set the reference to a $scoped object

//bootstrapping from MVC controller
    $scope.myObject = (bootStrappedData.someObject === "True");    

Here I was explicitly getting a boolean to work with ng-show or ng-hide but you can pass in a string or any other object if you want

Finally remember to set within your controller the dependency of the service you created within the page or it won't be defined

app.controller('myController', ['$scope', 'bootStrappedData' function(,scope, bootStrappedData)
...
]);

Comments

0

Thank you all. I now realize that I cannot, by design, mix MVC and AngularJS. In my case, I can just use MVC and not AngularJS but I wanted to get the best of both and start learning AngularJS as well so this is what I did. On the MVC side I populated my ViewModel and created a strongly typed View for that ViewModel. In the view I referenced my ViewModel like this:

@model Project_X_01202015_Web.ViewModel.ConsultantViewModel

than I created my AngularJS parts as normal with the exception of this:

$scope.user = { id: 1, isVerifiedUser: '@Model.UserBaseViewModel.IsVerifiedUser', firstName: '@Model.UserBaseViewModel.FirstName', middleName: '@Model.UserBaseViewModel.MiddleName', lastName: '@Model.UserBaseViewModel.LastName', email: '@Model.UserBaseViewModel.Email', address: '@Model.UserBaseViewModel.Address', address1: '@Model.UserBaseViewModel.Address1', phoneNumber: '@Model.UserBaseViewModel.PhoneNumber', cell: '@Model.UserBaseViewModel.PhoneNumber1', city: '@Model.UserBaseViewModel.CityName', postalCode: '@Model.UserBaseViewModel.PostalCode', state: '@Model.UserBaseViewModel.StateName' };

I can change the value of the properties in $scope.user on the view and when I need to update my ViewModel object which is populated from the database I will have to update my database with the values first and than repopulate my ViewModel and give it back to the view or just update the current ViewModel instance and refresh the page. But instead of refreshing the page what I did is update the view and send a call to the MVC controller to update the database as well. This way view is updated and whenever user refreshes the page actual data is presented from database, information on the UI does not change.
I could update the $scope.user values like this: $scope.user.city = "Huntsville"; and when I needed to send any information back to the MVC controller I did this: url: '/Consultant/SaveConsultantInformation', async: 'false', type: 'POST', dataType: 'json', data: { user: $scope.user }, in my post call. I did have some issues with the AngularJs post/get and not being able to update the $scope.user value from the success: function (result) {} of the post/get and ng-hide/ng-show being more involved for basic use than a simple $('#verifyMeButton').hide(); but I did a non AngularJS workaround for that. Over all I think AngularJS is a great too for getting around in the UI and I will continue to use it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.