Anson Tan
Anson Tan

Reputation: 1246

How IBM MobileFirst Adapter integrate with Angular JS?

I am using IBM MobileFirst + Ionic + AngularJS, to create a program that search customer by name and list the result in a table.

Let's said I have a adapter :

<wl:adapter name="customerAdapter"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:wl="http://www.ibm.com/mfp/integration"
xmlns:sql="http://www.ibm.com/mfp/integration/sql">
<displayName>customerAdapter</displayName>
<description>customerAdapter</description>
<connectivity>
  <connectionPolicy xsi:type="sql:SQLConnectionPolicy">
     <dataSourceDefinition>
        <driverClass>oracle.jdbc.driver.OracleDriver</driverClass>
            <url>jdbc:oracle:thin:@//10.128.2.155:1521/MyDB</url> 
            <user>admin</user>
            <password>admin</password>
        </dataSourceDefinition>
    </connectionPolicy>
</connectivity>
<procedure name="searchCustomerByIC"/>
<procedure name="searchCustomerByNM"/>
<procedure name="searchCustomerByICandNM"/>

and this is the implementation : (For searchCustomerByNM)

var statementSearchCustomerByNM= WL.Server.createSQLStatement("select CUST_NM,CUST_NIRC,CUST_GENDER from TB_CUSTOMER where CUST_NM like UPPER(?) ");
function searchCustomerByNM(customerName) {
    return WL.Server.invokeSQLStatement({
       preparedStatement : statementSearchCustomerByNM,
       parameters : [new String("%" + customerName + "%")]
  });
}

The adapter work well.

Here is my GUI code:

<ion-view view-title="Customer">
 <ion-content>
 <div id = "pageCustomer">
    <div class="list">
      <label class="item item-input">
        <input type="text" placeholder="Customer Name" ng model="customerName">
      </label>
      <label class="item item-input">
        <input type="text" placeholder="Customer IC" ng-model="customerIc">
      </label>
      <button class="button button-full button-positive" ng-click="customerSearch(customerName)">
        Search Customer
    </button>
    </div>
    <hr>
    <table id="myTable" cellpadding="5" align="center" >
    <thead>
    <tr>
        <th data-priority="2">Name</th>
        <th data-priority="1">NIRC</th>
        <th data-priority="persist">Gender</th>
        <td></td>
    </tr>
    </thead>

      <tr ng-repeat="x in customers">
        <td>{{ x.name }}</td>
        <td>{{ x.ic}}</td>
        <td>{{ x.gender }}</td>
      </tr>
    </table>    
  </div>
</ion-content>
</ion-view>

Here is my services:

app.service("customerSearchService",function()
{
    this.searchByName = function(name){

            var invokeData = {
                 adapter:"customerAdapter",
                 procedure:["searchCustomerByNM"],
                 parameters:[name]
             };

            var options = {
                 onSuccess:loadSQLQuerySuccess,
                 onFailure:loadSQLQueryFailure,
                 invocationContext:{'action':'Search Customer'}
             };

            WL.Client.invokeProcedure(invokeData,options);
            function loadSQLQuerySuccess(result){
                var customers = new Array();
               var SJ = JSON.parse(JSON.stringify(result));
               var length = SJ.invocationResult.resultSet.length;
               for(var i=0;i<length;i++)
               { 
                    customers[i] = {name:SJ.invocationResult.resultSet[i].CUST_NM , ic:SJ.invocationResult.resultSet[i].CUST_NIRC , gender:SJ.invocationResult.resultSet[i].CUST_GENDER};
               }
               return customers;     
            }
           function loadSQLQueryFailure(){
               console.log("failureSend");
               alert("failureSend");
               var customers = new Array();
               return customers; 
           }
    }
});

This is my controller:

app.controller('CustomerCtrl', function($scope,   customerSearchService,busyIndicator) {
$scope.getCustomers = function(customerName)
{
    $scope.customers = [];
    busyIndicator.show();
    $scope.customers = customerSearchService.searchByName(customerName);
    alert($scope.customers);
    busyIndicator.hide();
};
$scope.customerSearch=function(customerName){   
    $scope.getCustomers(customerName);
}

})

How should I write a service and controller ? (provide code in my case please) I tried before, but my function keep return empty result, because the result is returned before the adapter fetch all data. How to wait the adapter get all data ?

Thanks in advance.

Upvotes: 1

Views: 1027

Answers (3)

Karl Bishop
Karl Bishop

Reputation: 251

Might I also recommend that you read and follow Raymond Camden's blog. He's done several posts on MFP and Ionic, including adapter usage.

http://www.raymondcamden.com/

Upvotes: 1

Srik
Srik

Reputation: 7957

Can you try using $q ( https://docs.angularjs.org/api/ng/service/$q ) in your service

app.service("customerSearchService",function($q) // Add $q 
{
    this.searchByName = function(name){
        var deferred = $q.defer();
        var invokeData = {
             adapter:"customerAdapter",
             procedure:"searchCustomerByNM", // Note this is not an array
             parameters:[name]
         };

        var options = {
             onSuccess:loadSQLQuerySuccess,
             onFailure:loadSQLQueryFailure,
             invocationContext:{'action':'Search Customer'}
         };

        WL.Client.invokeProcedure(invokeData,options);
        function loadSQLQuerySuccess(result){
            var customers = new Array();
           var SJ = JSON.parse(JSON.stringify(result));
           var length = SJ.invocationResult.resultSet.length;
           for(var i=0;i<length;i++)
           { 
                customers[i] = {name:SJ.invocationResult.resultSet[i].CUST_NM , ic:SJ.invocationResult.resultSet[i].CUST_NIRC , gender:SJ.invocationResult.resultSet[i].CUST_GENDER};
           }
           //return customers;     
           deferred.resolve(customers);
        }
       function loadSQLQueryFailure(){
           console.log("failureSend");
           alert("failureSend");
           var customers = new Array();
           //return customers; 
           deferred.reject(customers);
       }

       return deferred.promise;
    }
});

Upvotes: 1

Nathan H
Nathan H

Reputation: 49371

The main issue is that your searchByName does not return anything. Look closely, you'll see that the only return statements are within other functions. So, your function call will end without returning anything. And like you said, it will return even before the invocation finished.

What you are experiencing is a typical flow of asynchronous services.

I know of 2 approaches to this issue:

  • Promises: Promises allow you to "wait" for an answer in a way, like you asked.

Read about Promises in general: http://www.html5rocks.com/en/tutorials/es6/promises/

Read about Promises in AngularJS: https://docs.angularjs.org/api/ng/service/$q

Read about Promises in Services: http://chariotsolutions.com/blog/post/angularjs-corner-using-promises-q-handle-asynchronous-calls/

  • AngularJS broadcast Broadcast allows you to send a message from one place (your service) and receive it in another place (your controller). So you can ping your controller when you finished: $on and $broadcast in angular

Upvotes: 1

Related Questions