5

I have a trouble to get angular working with .Net partial postbacks.

Question is basically same to this : Re-initialize Angular bindings after partial postback

Basically I have a tab on which I have angular app, then I have second tab with some c# control, I have to do partial postback between tabs and when I am going back to my app, there is nothing.

I have tried routing with ngView then I have tried $route.reload() (it goes to the controller and I can see that the template is being pulled down but the result on the page is none). Then I tried compile(templateCache.get(lazyTableControllerRoute.current.templateUrl))(scope) as mentioned here. Nothing.

Please help :)

After each postback I am putting on page this html :

LiteralControl lazyControl = new LiteralControl("<div ng-app=\"LazyLoadingApp\" style=\"padding:10px\" ng-controller=\"LazyTableController\" ng-view><lazy-table> </lazy-table></div>");
Controls.Add(lazyControl);

And some config constants like templateUrl.

Here is my code :

var app = angular.module('LazyLoadingApp', ['ui.bootstrap', 'ngRoute'], function ($interpolateProvider) {
    $interpolateProvider.startSymbol('[[');
    $interpolateProvider.endSymbol(']]');
});

app.config(function ($routeProvider, $locationProvider, tableTemplateUrl) {
    $routeProvider.when('/Page.Web.UI/sptl_project.aspx', {
        controller: 'LazyTableController',
        templateUrl: tableTemplateUrl,
    });

    // configure html5 to get links working on jsfiddle
    $locationProvider.html5Mode(true);
});

//**This objects I am using after partial postback to check in the console if e.g. $route.reload() works..**
var lazyTableControllerRoute = null;
var templateCache = null;
var compile = null;
var scope = null;

app.directive('lazyTable', ['tableTemplateUrl',

    function (tableTemplateUrl) {
        return {
            name: 'lazyTable',
            priority: 0,
            restrict: 'E', // E = Element, A = Attribute, C = Class, M = Comment
            templateUrl: tableTemplateUrl
        };
    }
]).controller('LazyTableController', ['$scope', '$rootScope', 'lazyFactory', 'opsPerRequest', 'header', '$route', '$templateCache', '$compile',

    function ($scope, $rootScope, lazyFactory, opsPerRequest, header, $route, $templateCache, $compile) {

        lazyTableControllerRoute = $route;
        var loadingPromise = null;
        templateCache = $templateCache;
        compile = $compile;
        scope = $scope;

(...) rest is not important 

UPDATE:

I was trying with require.js.. (Again, it's working after full page load.) My idea was to bootstrap element after partial postback. I built simple test case that in Update Panel along with my app there is simple button, just making partial postback. After click (when app disappeared) I tried in console:

angular.bootstrap(document, ['LazyLoadingApp'])

But then I got error which I cannot remove:

App Already Bootstrapped with this Element 'document'

Here is plunker for app in require.js way (but please keep in mind that it's just for code review purpose..)

Community
  • 1
  • 1
Daniel F
  • 53
  • 9

3 Answers3

0
  • don't use ng-app and angular.bootstrap all together at once.
  • did you compile "ng-app", if so don't.

ngtutorial.com/learn/bootstrap

sss
  • 1,259
  • 9
  • 23
  • Thank you for your answer. I am not using it togheter, when I tried "require.js way" I did remove ng-app tag. – Daniel F Sep 04 '14 at 11:20
  • how is lazycontrol used? why it contains ng-app? – sss Sep 04 '14 at 11:22
  • You can see here that lazycontrol contains ng-app because that was my first approach - normal angular injecting. Please don't connect code above "UPDATE" with update itself because I did some changes for require.js to work - like removing ng-app from the page and adding ngview.. – Daniel F Sep 04 '14 at 11:27
  • here you go, but keep in mind that it won't work on plunker :) I don't know how to simulate partial postbacks there.. and create a working ashx service.. http://plnkr.co/edit/SM6hYWubePLcfvgyeu0F?p=preview – Daniel F Sep 04 '14 at 11:41
  • Above plunker is for my version after UPDATE, so with require.js way. – Daniel F Sep 04 '14 at 11:47
  • hmmm, don't see anything that could call bootstrap twice. in this kind of problem, i would use firefox's debug at the same time modify angular.js code to add logging. – sss Sep 04 '14 at 11:57
0

Alright ! Problem solved.. So in order to work with partial postbacks you need to :

Define app like this: (remember that you have to remove ng-app from html !)

<base href="/">
<asp:UpdatePanel ID="updatePanel" runat="server" UpdateMode="Conditional">
    <ContentTemplate>
         <asp:Button ID="fire" runat="server" Text="fire!" />
            <div id="parent" >  <div id="boodstapped" ng-view ></div></div>

    </ContentTemplate>
</asp:UpdatePanel>

Instantiate app like this:

var app = angular.module('LazyLoadingApp', ['ui.bootstrap', 'ngRoute']);
jQuery(document).ready(function ($) {
    var prm = Sys.WebForms.PageRequestManager.getInstance();
    function EndRequestHandler(sender, args) {
        jQuery('#parent').children().remove();
        jQuery('#parent').append('<div id="boodstapped" ng-view ></div>');
        angular.bootstrap(jQuery('#boodstapped'), ['LazyLoadingApp']);
    }
    prm.add_endRequest(EndRequestHandler);
});

Then when you will try to do partial postback EndRequestHandler will bootstrap app again. What's important to remove previously bootstrap element, to avoid angular "already bootstrapped" error.

Click Here for more information.

Daniel F
  • 53
  • 9
0

Though the other answers probably do work I've found that best course of action is to try to not be in a 'mixed' state of .net controls and angular controls that depend on interaction between the two.

The process for this is undocumented at best... and you end up writing a lot of code to accommodate simple things.

I wouldn't recommend doing the following for long and only suggest it as a temporary/transitional solution and I know this may not solve every case .... but note you can always attack this problem from the dot.net side as follows and redirect back to the page you are on...

      protected void cbChecked_My_DotNet_CallBack(object sender, EventArgs e)
        {
             DoDotNetStuff();
             if(NeedToSignalToAngular){
                   response.redirect(yourpage.aspx?yourparams=xxx)     
             }
         }
Bob Sheehan
  • 160
  • 1
  • 6