简体   繁体   中英

Angular template and .NET Partial Postback

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..)

  • 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

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.

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)     
             }
         }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM