I am working on Extjs 4.1. I did implement an autocomplete feature for the text box. I'm now able to search for student's first or last name by entering a term, for example: Mat, and the result in text field would be:
Mathio,Jay << student's first and last name
Mark,Matt << student's first and last name
Then, I made some changes on the query so that i can get the subjects too when i search for one:
Mathio,Jay << student's first and last name
Mark,Matt << student's first and last name
Mathematics << subject
Here is my new query:
Query to search in multiple tables + Specify the returned value
Now, what i need is reconfigure the other parts so the field can display both cases, names and subjects
Here is my combo config:
,listConfig: {
loadingText: 'Loading...',
tpl: Ext.create('Ext.XTemplate',
'<tpl for=".">',
'<tpl if="l_name.length == 0"> ',
'<div class="x-boundlist-item">{f_name}<p><font size="1">Last Name: Unknown </font></p></div>',
'<tpl else>',
'<div class="x-boundlist-item">{f_name}<p><font size="1">{l_name}</font></p></div>',
'</tpl>',
'</tpl>'
),
and my model:
Ext.define("auto", {
extend: 'Ext.data.Model',
proxy: {
type: 'ajax',
url: 'auto.php',
reader: {
type: 'json',
root: 'names',
autoLoad: true,
totalProperty: 'totalCount'
}
},
fields: ['f_name','l_name'
, {
name : 'display',
convert : function(v, rec) {
return rec.get('f_name') + ',' + rec.get('l_name');
}
}
]
});
I tried many times but still can't reach a good way to do it.
IMO you'd better use a simple model with only a 'name' field, and populate this field on the server-side. From your previous question, the server code would look like (in your query processing loop):
if (isset($row[2])) { // if the query returned a subject name in the row
$name = 'Subject: ' . $row[2];
} else if (isset($row[1])) { // if we have the last name
$name = 'Student: ' . $row[0] . ', ' . $row[1];
} else { // we have only the first name
$name = 'Student: ' . $row[0] . ' (Uknown last name)';
}
$names[] = array(
'name' => $name,
);
On the client-side, you would use a model with a single name field, and configure your combo box accordingly:
// Your simplified model
Ext.define('Post', {
extend: 'Ext.data.Model'
,fields: ['name']
,proxy: {
// Your proxy config...
}
});
Ext.widget('combo', {
displayField: 'name'
,valueField: 'name'
// Remaining of your combo config...
});
However, if you really want to mix students and subjects data in one single model, here are the modification you should do on your current code. First, you need to retrieve the subject name from the server. That means changing your server code to something like:
$names[] = array('f_name' => $row[0], 'l_name' => $row[1], 'subject' => $row[2]);
Then you need to add this field in your model on the client side, and adapt your display field's convert method to account for subject:
Ext.define('Post', {
extend: 'Ext.data.Model'
,fields: ['f_name', 'l_name',
'subject', // Add the subjet field to the model
{
name: 'display'
// Adjust your convert method
,convert: function(v, rec) {
var subject = rec.get('subject'),
lastName = rec.get('l_name'),
firstName = rec.get('f_name');
if (!Ext.isEmpty(subject)) {
return subject;
} else {
if (Ext.isEmpty(lastName)) {
return firstName + ' (Unknown last name)';
} else {
return firstName + ', ' + lastName;
}
}
}
}
]
,proxy: {
// Your proxy config...
}
});
Finally, since you already do that work in the display field of the model, you should use it as the displayField of the combo instead of doing it again in the combo's template.
E.g. combo config:
{
displayField: 'display'
,valueField: 'display'
// Remaining of your combo config...
}
Related
I am having some difficulties with trying to add to cart with custom data from the front end.
My current PHP from the backend is as follows - this is placed in my functions.php for my child-theme (This code is from the following post: Adding a product to cart with custom info and price - considering I am indeed a PHP-noobie):
<?php // This captures additional posted information (all sent in one array)
add_filter('woocommerce_add_cart_item_data','wdm_add_item_data',1,10);
function wdm_add_item_data($cart_item_data, $product_id) {
global $woocommerce;
$new_value = array();
$new_value['_custom_options'] = $_POST['custom_options'];
if(empty($cart_item_data)) {
return $new_value;
} else {
return array_merge($cart_item_data, $new_value);
}
}
// This captures the information from the previous function and attaches it to the item.
add_filter('woocommerce_get_cart_item_from_session', 'wdm_get_cart_items_from_session', 1, 3 );
function wdm_get_cart_items_from_session($item,$values,$key) {
if (array_key_exists( '_custom_options', $values ) ) {
$item['_custom_options'] = $values['_custom_options'];
}
return $item;
}
// This displays extra information on basket & checkout from within the added info that was attached to the item.
add_filter('woocommerce_cart_item_name','add_usr_custom_session',1,3);
function add_usr_custom_session($product_name, $values, $cart_item_key ) {
$return_string = $product_name . "<br />" . $values['_custom_options']['description'];// . "<br />" . print_r($values['_custom_options']);
return $return_string;
}
//This adds the information as meta data so that it can be seen as part of the order (to hide any meta data from the customer just start it with an underscore)
add_action('woocommerce_add_order_item_meta','wdm_add_values_to_order_item_meta',1,2);
function wdm_add_values_to_order_item_meta($item_id, $values) {
global $woocommerce,$wpdb;
wc_add_order_item_meta($item_id,'item_details',$values['_custom_options']['description']);
wc_add_order_item_meta($item_id,'customer_image',$values['_custom_options']['another_example_field']);
wc_add_order_item_meta($item_id,'_hidden_field',$values['_custom_options']['hidden_info']);
}
and then I have a button on the frontend that runs the following script when pressed - this runs on a custom wordpress post where I have scripted have done some scripting in the background that collects information based on the users actions on the post:
function cartData() {
var metaData = {
description: 'My test Description'
another_example_field: 'test'
};
var activeVariationId = 10335;
var data = {
action: 'wdm_add_item_data',
product_id: 10324,
"add-to-cart": 10324,
quantity: 1,
variation_id: activeVariationId,
cart_item_data: metaData
};
$.ajax({
type: 'post',
url: wc_add_to_cart_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'add-to-cart' ),
data: data,
beforeSend: function (response) {
//$thisbutton.removeClass('added').addClass('loading');
},
complete: function (response) {
//$thisbutton.addClass('added').removeClass('loading');
},
success: function (response) {
if (response.error & response.product_url) {
window.location = response.product_url;
return;
} else {
alert('ajax response recieved');
jQuery( document.body ).trigger( 'added_to_cart', [ response.fragments, response.cart_hash ] );
}
},
});
}
Unfortunately this only seems to add my current variation of the product to the to cart without any more custom information. Any help with nesting in this issue would be highly appreciated. If you need any more information and/or code examples I'd be happy to supply it :)
I think that I might have solved it, or at least parts of it with this PHP (this is really just a small modification of this code - adding $cart_item_data https://quadmenu.com/add-to-cart-with-woocommerce-and-ajax-step-by-step/):
add_action('wp_ajax_woocommerce_ajax_add_to_cart', 'woocommerce_ajax_add_to_cart');
add_action('wp_ajax_nopriv_woocommerce_ajax_add_to_cart', 'woocommerce_ajax_add_to_cart');
function woocommerce_ajax_add_to_cart() {
$product_id = apply_filters('woocommerce_add_to_cart_product_id', absint($_POST['product_id']));
$quantity = empty($_POST['quantity']) ? 1 : wc_stock_amount($_POST['quantity']);
$variation_id = absint($_POST['variation_id']);
// This is where you extra meta-data goes in
$cart_item_data = $_POST['meta'];
$passed_validation = apply_filters('woocommerce_add_to_cart_validation', true, $product_id, $quantity);
$product_status = get_post_status($product_id);
// Remember to add $cart_item_data to WC->cart->add_to_cart
if ($passed_validation && WC()->cart->add_to_cart($product_id, $quantity, $variation_id, $cart_item_data) && 'publish' === $product_status) {
do_action('woocommerce_ajax_added_to_cart', $product_id);
if ('yes' === get_option('woocommerce_cart_redirect_after_add')) {
wc_add_to_cart_message(array($product_id => $quantity), true);
}
WC_AJAX :: get_refreshed_fragments();
} else {
$data = array(
'error' => true,
'product_url' => apply_filters('woocommerce_cart_redirect_after_error', get_permalink($product_id), $product_id));
echo wp_send_json($data);
}
wp_die();
}
Where this is part of the JS-function:
var data = {
action: 'woocommerce_ajax_add_to_cart',
product_id: 10324,
quantity: 1,
variation_id: activeVariationId,
meta: metaData
};
$.ajax({
type: 'post',
url: wc_add_to_cart_params.ajax_url,
data: data, ...........
I am going to have to test it some more, as it seems now that all the data-fields also gets posted in the cart, email etc - I probably have to rewrite something so that some parts of it is hidden for the "non-admin", but available for me later on + adding custom product thumbnail on add to cart.
In a single javascript file I have the following kendo grid option.
var relatedJobsGridOptions = ko.observable({});
//I am seeing message, javascript function is never used :(
function getName(name) {
return name;
}
relatedJobsGridOptions({
columns: [
{ field: 'name', title: 'Customer Name ', width: '160px' },
],
dataSource: OccData,
rowTemplate: (
'<tr style="background-color: rgb(246,246,246)" data-uid="#= uid #">' +
'<td>#=getName(name)# </td>' +
'</tr>'
),
overflow: false
});
How I can call the javascript function inside this rowTemplate?
I have referred few telerik forums, but as for as I searched none is matching my condition (My poor research :( I am completely got stuck here..)
Any suggestion would be helpful to me.
Just use a string interpolation:
function getName (name) {
return `<strong>${name}</strong>`
}
const rowTemplate = `
<tr style="background-color: rgb(246,246,246)" data-uid="#= uid #">
<td>#= ${ getName('some name') } #</td>
</tr>
`.trim()
console.log(rowTemplate);
I am creating a dgrid based on a data source which has an address and two columns with Boolean values which identifies what type of address is in the record, either postal address or business address.
I would like to display a descriptive name for the Boolean values in another column (Address Type) based on the two Boolean columns. I am trying to use the dgrid formatter function however i am unable to get the desired results. Under is my code:
Javascript
function getAddressType(){
$.each(employeeAddressData, function(key, value){
if(key == "postalAddress"){
if(value == true || value == 'true'){
console.log('returning postal');
return 'Postal';
}
}else{
console.log('returning business');
return 'Business';
}
});
}
var Employer = [{id: 1, businessName:'John Doe and Sons Limited',phone:'123456',address:'123 Long Street', postalAddress:true, businessAddress:false},
{id: 1, businessName:'Alice and Bob Limited',phone:'78956', address:'56 Short Street', postalAddress:false, businessAddress:true}];
var employerGrid = new CustomGrid({
store: employerStore,
columns:{
id:{
label:"Id",
field:"id",
hidden:true
},
businessName:{
label:"Business",
field:"businessName",
},
phone:{
label:"Contact No.",
field:"phone",
},
address:{
label:"Address",
field:"address",
},
addressType:{
label:"Address Type",
formatter:getAddressType();
}
},
selectionMode:"none",
loadingMessage: "Loading data...",
noDataMessage: "No results found....",
allowSelectAll: true
}, "employerGrid");
I realized dgrid has a get function which i can use to access the datasource attributes. So formatter was not needed instead get was used. Under is my solution :
Javascript
},
addressType:{
label:"Address Type",
get: function(object){
if(object.postalAddress == true){
return 'Postal';
}else{
return 'Business';
}
}
}
hi guys i have a couple of questions about ng-grid,
this is my grid-options
$scope.gridOptions= {
data:'data',
selectedItems:sel,
multiSelect:false,
columnDefs: [{ field: 'field1', displayName: 'field1',cellTemplate: template, cellClass:'cellToolTip'},
{field:'field2', cellTemplate: template, visible:false},
{ field:'field3', displayName:'field3', cellTemplate: template, cellClass:'cellToolTip' },
{ field: 'field4', displayName: 'field4',cellTemplate: templatetest} ,
{ field: 'dataInserimento', displayName: 'Data richiesta',cellTemplate: template, cellClass:'cellToolTip'} ,
{ displayName: 'field5', cellTemplate:'<div ><button ng-diasbled="pdfenabled" ng-click="reportpdf()"><i class="glyphicon glyphicon-file"></i></button></div>', cellClass:'gridCell' }]
}
}
and the two possible cell template are these
var template = '<div class="ngCellText" ng-class="col.colIndex()"><a id="gridField" ng-cell-text>{{row.getProperty(col.field)}}</a></div>';
var templatetest = '<div ng-disabled="enabled" class="ngCellText" ng-class="col.colIndex()"><a id="gridField" ng-cell-text>{{row.getProperty(col.field)}}</a></div>'
the data array is something similar to that one
[{field1:'something',
field2:'something',
field3:'something',
field4:[{otherstuff:'something',morestuff:'something'}],
field5:'something'}
{field1:'something',
field2:'something',
field3:'something',
field4:[{otherstuff:'something',morestuff:'something'}],
field5:'something'}
{field1:'something',
field2:'something',
field3:'something',
field4:[{otherstuff:'something',morestuff:'something'}],
field5:'something'}
}]
so the first problem is: how can i display the elements in the field4 field not like an array? is it possible to get only one or both values?
second question, it is possible to use a cell field property for another cell bind?
for example
if(field3==false){
$scope.enabled=true;
}
Write your template like this:
var templatetest = '<div ng-disabled="enabled" class="ngCellText" ng-class="col.colIndex()" ng-bind="row.getProperty(col.field)[0].otherstuff"></div>';
Look at this Plunker
Or even better you could use a filter:
app.filter('somefilter', function() {
return function(x) {
return x[0].otherstuff + ' / ' + x[0].morestuff;
};
});
in combination with this template:
var templatetest = '<div ng-disabled="enabled" class="ngCellText" ng-class="col.colIndex()" ng-bind="row.getProperty(col.field)|somefilter"></div>';
Look at this Plunker
Or (this includes the Answer to your second question) use row.entity to look up the full rowdata:
var templatetest = '<div ng-disabled="enabled" class="ngCellText" ng-class="col.colIndex()"> {{row.entity.field4[0].otherstuff+"/"+row.entity.field3}}</div>';
Here's the final Plunker
Hope you can get on with this.
I have a EXTjs grid, which displays some fields from my custome tables in database..
Reports.grid.Reports = function(config) {
config = config || {};
Ext.applyIf(config,{
id: 'reports-grid-reports'
,url: Reports.config.connectorUrl
,baseParams: { action: 'mgr/reports/getList' }
,save_action: 'mgr/reports/updateFromGrid'
,fields: ['id','name','filename','remark','year','resourceID','typeID','visible']
and then :
{
header: 'Type ID'
,dataIndex: 'typeID'
,sortable: true
,width: 100
}
My types table has typeid and name.. my grid displays the number, How can I tell it to display the coresponding name for that id in the table instead?
I also got a combobox which I use in update window:
Reports.combo.Types = function(config) {
config = config || {};
Ext.applyIf(config,{
name: 'typeID'
,hiddenName: 'typeID'
,displayField: 'name'
,valueField: 'id'
,fields: ['name','id']
,listWidth: 380
,pageSize: 20
,url: Reports.config.connectorUrl
,baseParams: {
action: 'mgr/reports/gettypelist2', 'combo': true
}
});
Reports.combo.Types.superclass.constructor.call(this,config);
};
Ext.extend(Reports.combo.Types,MODx.combo.ComboBox);
Ext.reg('combo-modx-types',Reports.combo.Types);
Using ,displayField: 'name' makes combo display name instead of the id.. how can I do the same thing in grid?
If I understand the question correctly, I believe you would need to customise the getList processor rather than in the ExtJS directly. Override the afterIteration() function. Something along the lines of:
public function afterIteration(array $list) {
$rows = array();
foreach ($list as $row){
// This calls a custom getName() function that gets the name from the other table
$row['typeID'] = $this->getName($row['id']);
$rows[] = $row;
}
return $rows;
}
and maybe your getName() function could be something like:
private function getName($id) {
$otherTable = $this->modx->getObject('TABLE_ALIAS_HERE', array('internalKey' => $id));
$name = $otherTable->get('name');
return $name;
}