1

In my application I'm returning the view below which uses this TestViewModel.

public class TestViewModel
{
    public List<string> Tests { get; set; }
}

View:

@model AdminSite.Models.TestsViewModel
    @{
        ViewBag.Title = "Tests";
    }

    <hgroup class="title">
        <h1>@ViewBag.Title</h1>
    </hgroup>

    <!doctype html>
    <html>
    <head>
        <script src="~/Scripts/Angular/angular.min.js"></script>
        <script src="~/Scripts/Angular/Tests.js"></script>
    </head>
    <body>
        <div ng-app="testsTable">
            <div ng-controller="TableController">
                <table my-table options="options"></table>
            </div>
        </div>
    </body>
    </html>

As you can see I'm using AngularJS to create a DataTable, what I would like though is that instead of the table data "aaData" being hardcoded I want it to be from TestViewModel model.

var app = angular.module('testsTable', []);

app.directive('myTable', function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs, controller) {
            var dataTable = element.dataTable(scope.options);
        },
        scope: {
            options: "="
        }
    };
});


app.controller('TableController', ['$scope', function ($scope) {
    $scope.options = {
        aoColumns: [
            {
                "sTitle": "Col 1",
            },
            {
                "sTitle": "Col 2"
            },
            {
                "sTitle": "Col 3"
            }
        ],
        aoColumnDefs: [{
            "bSortable": true,
        }],
        bJQueryUI: true,
        bDestroy: true,
        aaData: [
            ["A", "B", "C"],
            ["A", "B", "C"],

        ]
    };
}]);

I think I may have to create another directive to bind the model e.g

<table my-table options="options" model-data="@Model.Tests"></table>

but I'm not really sure how Angular directives work exactly, how I would write said directive & how it binds it to the scope

JustSomeDev
  • 324
  • 5
  • 18

3 Answers3

0

Your question is answered here

You could directly inject the values into JavaScript:

//View.cshtml
<script type="text/javascript">
    var arrayOfArrays = JSON.parse('@Html.Raw(Model.Addresses)');
</script>

See JSON.parse, Html.Raw

Alternatively you can get the values via Ajax:

public ActionResult GetValues()
{
    // logic
    // Edit you don't need to serialize it just return the object

    return Json(new { Addresses: lAddressGeocodeModel });
}

<script type="text/javascript">
$(function() {
    $.ajax({
        type: 'POST',
        url: '@Url.Action("GetValues")',
        success: function(result) {
            // do something with result
        }
    });
});
</script>

See jQuery.ajax

Community
  • 1
  • 1
Bruno João
  • 5,105
  • 2
  • 21
  • 26
  • it's not the serialisation part I'm struggling with it moreso how I set the scope to use that serialised data. what I want to achieve really is var arrayOfArrays = JSON.parse('@Html.Raw(Model.Addresses)') then $scope.option.aaData = arrayOfArrays – JustSomeDev Apr 19 '16 at 14:36
  • You can create this scope variable inside your controller and then assign the value to it. I think you are using DataTables. If so, the table should get updated after you cahnge the array content. In your HTML just use {{myVariable=JSON.parse('@Html.Raw(Model.Addresses)');""}} – Bruno João Apr 19 '16 at 14:40
  • In your HTML just use `{{options.aaData=JSON.parse('@Html.Raw(@Model.Tests)');""}}` before the table tag. Let me know if it worked so I'll edit my answer. – Bruno João Apr 19 '16 at 14:48
  • still no luck, just in case the serialisation part isn't working ive simplified the line you have given me to `{{options.aaData = [["A","B","C"],["1","2","3"]];""}}` – JustSomeDev Apr 19 '16 at 15:14
0

So...Setting aaData using {{options.aaData=JSON.parse('@Html.Raw(@Model.Tests)');""}} was working but I had nothing monitoring the change meaning the table wasn't being redrawn with the new information.

to track changes I added a watch in my directive, this monitors aaData for changes then updates the table as necessary.

scope.$watch('options.aaData', handleUpdate, true);
function handleUpdate(newData) {
                var data = newData || null;
                if (data) {
                    dataTable.fnClearTable();
                    dataTable.fnAddData(newData);
                }
            }

my real solution looks a little different now as I am using dataTables ajax call to pull down my json data then setting the dataSrc with the result. Using the in-built ajax calls means I can remove the directive watch as datatables handles this for me.

One final note, if you've found yourself here while figuring out how to mix angularJS & dataTables then this fiddle has helped me a lot. http://jsfiddle.net/TNy3w/2/

JustSomeDev
  • 324
  • 5
  • 18
0

Since you're working with angular, take advantage of angular configuration:

<script>
    (function () {
        angular.module('app').value('mydata', {
            propOne: '@Url.Action("Index", "Dirty", null)',
            propTwo: angular.fromJson('@Html.Raw(Model.Addresses)')
            // more properties here
        });
    })();
</script>

Then you can inject and use 'mydata' anywhere within your angular application

EDIT: You can create an extension method that serializes your model to JSON, then Html.Raw won't give you an error, as long as the parameter you provide is not null.

public static class ObjectExtensions { public static string SerializeObject(this object obj) { return JsonConvert.SerializeObject( obj, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }); } }

Then do:

@using [static extension class namespace here]; ... angular.fromJson('@Html.Raw(Model.Addresses.SerializeObject())')

DrinkBird
  • 834
  • 8
  • 17