Search code examples
ajaxangularjsbreeze

breeze 1.4.8 & angular ajax adapter: how to customize ajax settings?


My code:

breeze.config.initializeAdapterInstance("ajax", "angular", true);

...

var ajaxAdapter = breeze.config.getAdapterInstance('ajax');

ajaxAdapter.defaultSettings = {
    method: 'POST',
    data: {
        CompanyName: 'Hilo Hattie',
        ContactName: 'Donald',
        City: 'Duck',
        Country: 'USA',
        Phone: '808-234-5678'
    }
};

in line 14813 of breeze.debug.js:

ngConfig = core.extend(compositeConfig, ngConfig);

compositeConfig.method has a value of 'POST' until it is overwritten, because ngConfig.method has a value of 'GET'.

I imagine this question is relevant for any ajax setting, but of course I'm mainly struggling with how to post with the angular ajax adapter, so maybe there's an entirely better way to do that? this approach feels dirty anyway, but breeze.ajaxPost.js only works with the jQuery ajax adapter, right?


Solution

  • 6 Oct 2014 update

    We recently had reason to revisit ajaxpost and have updated both the code and the documentation.

    The original recommendation works. We're merely clarifying and updating the happy path.

    A few points:

    • The ajaxpost plug-in works for both jQuery and Angular ajax adapters.

    • Those adapters long ago became aware of adapter.defaultSettings.headers and have blended them into your Breeze ajaxpost http calls (take heed, PW Kad).

    • You must call breeze.ajaxPost() explicitly after replacing the default ajax adapter as you do when you use the 'breeze.angular' service.

    • You can wrap a particular ajax adapter explicitly: breeze.ajaxPost(myAjaxAdapter); We just don't do that ourselves because, in our experience, it is sufficient to omit the params (breeze.ajaxPost()) and let the method find-and-wrap whatever is the active ajax adapter of the moment.

    The documentation explains the Angular use case which I repeat here to spare you some time:

    // app module definition
    var app = angular.module('app', ['breeze.angular']);  // add other dependencies
    
    // this data service abstraction definition function injects the 'breeze.angular' service
    // which configures breeze for angular use including choosing $http as the ajax adapter
    app.factory('datacontext', ['breeze', function (breeze) {    // probably inject other stuff too
        breeze.ajaxPost(); // wraps the now-current $http adapter
        //... your service logic
    }]);
    

    Original reply

    AHA! Thanks for the plunker (and the clever use of the Todo-Angular sample's reset method!).

    In brief, the actual problem is that breeze.ajaxpost.js extends the jQuery ajax adapter, not the angular ajax adapter. There is a timing problem.

    The root cause is that you can't tell breeze.ajaxpost.js which adapter to wrap. It always wraps the default adapter at the time that it runs. As you've got your script loading now, the jQuery adapter is the current one when breeze.ajaxpost.js runs.

    The workaround is to set the default adapter to the angular adapter before breeze.ajaxpost.js runs.

    One way to do that is to load the scripts as follows ... adding an inline script to set the default ajax adapter to the "angular" version.

      <script src="breeze.debug.js"></script>
      <script>
            <!-- Establish that we will use the angular ajax adapter BEFORE breeze.ajaxpost.js wraps it! -->
            breeze.config.initializeAdapterInstance("ajax", "angular", true);
      </script>
      <script src="breeze.ajaxpost.js"></script>
    

    Clearly this is a hack. We'll look into how we can change breeze.ajaxpost.js so you can wrap any ajax adapter at the time of your convenience.