Question

I'm new to AngularJS, so this might be a trivial question.

The problem I'm facing is that the AngularJS bindings {{Object.Field}} reverting to un formatted state whenever there is an update-panel partial update. I understand that the update-panel is replacing the DOM with the non formatted text({{Object.Field}}), but I'm not able to make angular re-evaluate the piece of HTML that was injected by the update panel.

What I've tried so far:

  • Got a handle to the scope of the controller from the End_Request of the update panel and wrapped the update function on the controller inside of a $scope.apply();
  • Called the $scope.compile at the same place and also inside the controller, with no result changes.
  • Tried replacing with a directive, but I don't think this is what I want.

I can get a handle to the DOM inside the controller and change it directly, but I understand that this is not a recommended approach and hence I'm here asking this question.

How do I make angular re-evaluate the piece of HTML, replaced/injected by an asp.net update panel's partial update?

Was it helpful?

Solution

You need to compile the template again within the End_Request of PageRequestManager. I used a div with an id so I could reference the element of interest within the End_Request function.

The javascript code:

var mod = angular.module("myApp", []);

mod.controller("MainController", function ($scope, $compile) {
    $scope.data = {};
    $scope.data.world = "world";

    Sys.WebForms.PageRequestManager.getInstance().add_endRequest(function (sender, args) {
        var elem = angular.element(document.getElementById("angularTemplate"));

        elem.replaceWith($compile(elem)($scope));
        $scope.$apply();
    });
});

The aspx code:

<body ng-app="myApp" ng-controller="MainController">
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
        <asp:UpdatePanel ID="UpdatePanel1" runat="server">
            <ContentTemplate>
                <div id="angularTemplate">
                    Hello, {{data.world}}
                </div>

                <asp:Button ID="btnUpdate" runat="server" Text="Update Me" />
            </ContentTemplate>
        </asp:UpdatePanel>
    </div>
    </form>
</body>

Clicking the "Update Me" button will keep "Hello, world" in the template. The key is to also call $scope.$apply() in the End_Request as this is technically run outside of angular.

OTHER TIPS

If you have a dynamic content and Angular bindings, this solution might not be enough for you.

I've tried to implement this solution and it almost worked. I saw the HTML content of the directive that inside the .NET application, but all Angular bindings, like ng-repeat and ng-click, didn't work.

I've found the solution here:

http://blog.travisgosselin.com/integrating-angularjs-in-a-tight-spot/

You need to manually initialize your module in the add_endRequest event:

Sys.WebForms.PageRequestManager.getInstance().add_endRequest(function (sender, args) {
                angular.bootstrap($('#myDiv'), ['myNgApp']);
            });

This solution was enough, and I removed the solution with the $compile.

You can read about angular.bootstrap in the documentation: https://docs.angularjs.org/guide/bootstrap

These solution are good and well enough explained. But still if some-one is struggling with asp.net Update panel and AngularJs, Here's one shot but unethical solution

First define a global variable in your aspx page

var myTempScope;

Then do this in you document.ready event

$(document).ready(fucntion(){
    myTempScope = angular.element($("#myAngularDiv")).scope() ;
});

and then when you are calling an angular function from your aspx page like

function callAngularFunction() {
    if(angular.element($("#myAngularDiv")).scope() == undefined)
        myTempScope.AngularFunction();
    else
       angular.element($("#myAngularDiv")).scope().AngularFunction();
}

In my case this was working fine.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top