Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

Description

In this example the last sample will be modified to make use of the FilterBuilder and the underlying AdvancedCriteria system, to build functionality resembling this showcase sample (but using our supplyItem DataSource, instead of the one in the webpage)

Prerequisites

As this sample extends the previous one, in order to be able to run it, please ensure you have the latest build of SmartClient (at least version 8.3p). This can be downloaded from here.

Adding FilterBuilder to front-end

Modify Scripts/ui.js to include the relevant code for creating the FilterBuilder:

ui.js
isc.FilterBuilder.create({
    ID: "advancedFilter",
    dataSource: "supplyItem",
    topOperator: "and"
});

The ListGrid also requires additional code to add the FilterBuilder. This will require adding a vertical layout (VStack), together with the grid and the button needed to add for applying the filter on the ListGrid. Also going to add a horizontal layout (HStack) which will contain the two already existing buttons used for saving all data and creating a new record:

ui.js
isc.ListGrid.create({
    ID: "supplyItemGrid",
    width: 700, height: 224, alternateRecordStyles: true,
    dataSource: supplyItem,
    autoFetchData:true,
    dataPageSize:20,
    canEdit:true,
    canRemoveRecords:true,
    autoSaveEdits: false
});
isc.IButton.create({
    ID: "filterButton",
    title: "Filter",
    click: function () {
        supplyItemGrid.filterData(advancedFilter.getCriteria());
    }
});
isc.HStack.create({
    membersMargin: 10,
    ID: "gridButtons",
    members: [
        isc.IButton.create({
            top: 250,
            title: "Edit New",
            click: "supplyItemGrid.startEditingNew()"
        }),
        isc.IButton.create({
            top: 250,
            left: 100,
            title: "Save all",
            click: "supplyItemGrid.saveAllEdits()"
        })
    ]
});
isc.VStack.create({
    membersMargin: 10,
    members: [advancedFilter, filterButton, supplyItemGrid, gridButtons]
});

Also note, the filter has been removed top of the grid, as it is being replaced with the FilterBuilder.

Parsing the AdvancedCriteria

The AdvancedCriteria built by the FilterBuilder is sent in the JSON payload when doing a fetch() request. It is formatted like this:

AdvancedCriteria JSON Foramat
// an AdvancedCriteria
{
    "_constructor":"AdvancedCriteria",
    "operator":"and",
    "criteria":[
        // this is a Criterion
        { "fieldName":"salary", "operator":"lessThan", "value":"80000" },
        { "fieldName":"salary", "operator":"lessThan", "value":"80000" },
            ...  possibly more criterions ..
        { "operator":"or", "criteria":[
            { "fieldName":"title", "operator":"iContains", "value":"Manager" },
            { "fieldName":"reports", "operator":"notNull" }
            { "operator":"and", "criteria": [
                .. some more criteria or criterion here
            ]}
        ]}
        },
        { "operator":"or", "criteria":[
            { "fieldName":"title", "operator":"iContains", "value":"Manager" },
            { "fieldName":"reports", "operator":"notNull" }
        ]}
            .. possibly more criterions or criterias
    ]
}

As you can see it is a tree structure, with it's leafs being criterion and the nodes being criteria. If the the criteria member is null, then it is a leaf, otherwise it is a node which has sub-criterias or sub-criterions.

Changes to DSRequest

Store an AdvancedCriteria condition data in the DSRequest object by adding a new property to it:

DSRequest.php
var $advancedCriteria;
public function getAdvancedCriteria()
{
	return $this->advancedCriteria;
}
// set the advanced criteria
public function setAdvancedCriteria($advancedCriteria)
{
	$this->advancedCriteria = $advancedCriteria;
}

The rest of the DSRequest's code remains unchanged. This new property will be initialized from the RPCManager which will load advanced criteria if the request has one during the parsing of the DSRequest objects.

Firstly, a helper method is needed in the RPCManager to decide if the DSRequest has AdvancedCriteria or not:

RPCManager.php
private function checkAdvancedCriteria($data)
{
	$blCheck = array_key_exists("_constructor", $data) && array_key_exists("operator", $data);
	return $blCheck;
}

Define a method which iterates over the list of requests in the transaction and for each load the advanced criteria if the request has one:

RPCManager.php
protected function parseAdvancedCriterias($operations)
{
	$data = $operations['data'];
	 
	if($this->checkAdvancedCriteria($data))
	{                     
		 return $data;
	}
	return null;
}

This method receives the operation list from request. Now modify the processTransaction in RPCManager to parse the advanced criteria:

RPCManager.php
private function processTransaction()
{
  // retrieve the requests with data in form of supplyItem
	// store transaction num, we'll use it later to see if there was a transaction or not
	$transactionNum = $transaction_request['transactionNum'];
	$idx = 0;
	$queueFailed = false;
				
	$res_list = array();
	$operations = $transaction_request['operations'];
	// create transaction
	R::begin();
	try{
		foreach($operations as $op)
		{        
			$res = $op;               
			// parse advanced criterias, if any
			$advancedCriteria = $this->parseAdvancedCriterias($op);
			 ... ... ... ... ...		
		}                            
		
		// if there were no errors, commit the transaction
		if (!$queueFailed)      
		{
			 R::commit();
		}                 
	}
	catch(Exception $e) {
		R::rollback();
	}
	... ... ... ... ... 
}

Refactor the existing fetch() method and move out the existing criteria building code into a  separate method called buildStandardCriteria():

DataSource.php
private function fetch($request)
{               
	// get the DataSource
	$ds = $this->data_source;   
	$tbl_name = $ds['ID'];   
	// check the advanced cretira
	if(empty($request->advancedCriteria)) 
	{
		$query_result = $this->buildStandardCriteria($request); 
	} else
	{
		$query_result = $this->buildAdvancedCriteria($request);                
	}
	
	$query = "select * from $tbl_name s ";
	$query .= $query_result;
   
	// sort by
	if( !empty($request->sortBy) )
	{
		// set the orderBy
		$query .= " order by ";
		
		// we start to build a coma separated list of items. First item won't have coma
		// but every possible next will do
		$seperator = "";
		foreach($request->sortBy as $index => $sort)
		{ 
			
			// if column name is with -, then ordering is descending, otherwise ascending
			if ( strpos($index, '-') === 0 )
			{
				$query .= $seperator . $sort . " ASC";
			} else
			{
				$query .= $seperator . substr($sort, 1) . " DESC";
			}
			$separator  = ',';
		}
	}
	
	//DSResponse
	$response = new DSResponse();                 
	$products = R::getAll($query);   
	// get the count                    
	$count = count($products);           
	$response->setData($products);
	$response->setStartRow($request->startRow);
	$response->setEndRow($request->endRow);            
	$response->setTotalRows($count);
	$response->setStatus(0);  
	
	// sanity check, if no rows, return 0
	if ($response->getEndRow() < 0 ) 
	{
		$response->setEndRow(0);
	}
	
	return $response;
 
}
 
private function buildStandardCriteria($request)
{
	$query = '';  
	$query_count = '';
	
	if ( count($request->getDataKeys()) != 0 )
	{
	   $query .= ' where ';               
		 
		foreach($request->data as $key => $value)
		{                       
			// get the field    
			$field = $this->getField($key);
			if(!empty($field))                                        
			{
				$type = $field['type'];
				
				if( $type == "text" ||
					$type == "link" ||
					$type == "enum" ||
					$type == "image" ||
					$type == "ntext" )
				{
					$query .= "s." . $key . " like " . " '%" . $value . "%' and " ;        
				} else
				{
					"s." . $key . "=" . " '" . $value . "' and " ;        
				}
			}
								
			$query_count .= "s." . $key . " like " . "'%" . $value . "%' and " ;            
		}
		
		// remove 'and' of the query                 
		$query = substr($query, 0, strrpos($query, 'and'));           
	}    
				
	return $query;
}
  • No labels