I'm moving my application to new server, and have been hitting into some issues lately.
PHP version: 5.5.34, Mac OSX Apache 2.4
Laravel version: 4.2
I get a grid but my browser complains for URL.
My ajax requests looks like:
$(grid_name).jqGrid({
//to get this function working make sure you've .htaccess file
//url:'illumina_xhr_get_data', - won't work if not added illumina
url:"illumina/illumina_xhr_get_samples",
//url:"illumina/illumina_xhr_get_samples",
datatype: "json",
mtype: "GET",
jsonReader: {
repeatitems: false,
id: "",
root: function (obj) {
return obj;
},
records: function (obj) {
return obj.length;
},
page: function () {
return 1;
},
total: function () {
return 1;
}
},
colNames:['Study','Sample Name','Forward Primer',
'Reverse Primer','Region','Read Length','Seq Platform', "ID"], //id is hidden.. that is used while making group
colModel :[
{name:"study_name",sortable: true},
{name: "sample_name",sortable: false},
{name: "forward_primer",sortable: false},
{name: "reverse_primer",sortable: false},
{name:"region",sortable:false},
{name:"read_length",sortable:false,align:'right'},
{name:"seq_platform",sortable:false},
{name:"id",sortable:false,hidden:true}
],
rowNum:10, //this sets the default row in the pager
caption:"Illumina", //title of the grid
pager: pager_name,
shrinkToFit : false,
rownumbers: true, //row numbers on left
multiselect: true, //check box
height: '400', //height: 'auto',
width: '1100',
gridview: true,
viewrecords:true, // this is for the View 1 - 8 of 8 \m/
sortorder:"asc", //asc
autoencode: true, //don't know
sortable:true, //sort
loadonce: true, //loadonce is must
rowList:[500,1000,1500], //drop down
page: 1,
rowNum: 100,
ignoreCase: true, //make search as case insenstive -- YAY.. Party
grouping:true, //this is for grouping
groupingView : { groupField : ['study_name'], //grouping based on study column
groupText : ['<b>{0} - {1} Sample(s)</b>'] //this will give count of samples present
} ///grouping view ends
});
`
Error:
The requested URL /pims/public/illumina/illumina_xhr_get_samples was not found on this server.
My local host points to ~/Sites
The same code works on my other machine (from which I'm transitioning).
I'm unable to figure out a solution to this. Kindly help.
I found the solution from: .htaccess: Invalid command 'RewriteEngine', perhaps misspelled or defined by a module not included in the server configuration
I'd to enable re-write module in order to be it read by server.
I found error in /var/log/apache2/error_log
Hope it helps someone. Thank you.
Related
I've been assigned a task to extent and modify a Shopware plugin. The original author isn't in the company anymore. Before that I've never dealt with Shopware and ExtJs.
So I spend the last couple of days getting myself into it and I think I understood the principles and paradigm so far.
The only thing I'm having trouble with right now is the following issue:
I've got an Ext.tree.Panel which I want to save into a database using Ajax. The node is being added to the tree, I can see it appearing in the GUI. But after calling optionsTree.getStore().sync() there is nothing arriving in the database. The createProductOptionAction() in the PHP controller isn't called, but I can't figure out why. There is no error message in Browser console log, no error message in the Shopware log files. Nothing. Everything seems to work fine. But the data isn't being stored.
The original plugin had an Ext.grid.Panel to store and display data. And this works fine. But after changing to Ext.tree.Panel and modifying the code, it doesn't work anymore. From my point of view it should work tho. But it doesn't and I can't see my mistake(s).
Any help is really appreciated, I'm still a bloody beginner with ExtJs. :)
Here is what I've got so far:
app.js
Ext.define('Shopware.apps.CCBConfigurablePhotoProductsManager', {
extend:'Enlight.app.SubApplication',
name:'Shopware.apps.CCBConfigurablePhotoProductsManager',
bulkLoad: true,
loadPath:'{url controller="CCBConfigurablePhotoProductsManager" action="load"}',
controllers:['ProductConfigurator'],
stores:['ProductOptionsList'],
models:['ProductOption'],
views: ['ProductOptions', 'Window' ],
launch: function() {
var me = this,
mainController = me.getController('ProductConfigurator');
return mainController.mainWindow;
}
});
controller/controller.js
Ext.define('Shopware.apps.CCBConfigurablePhotoProductsManager.controller.ProductConfigurator', {
extend:'Ext.app.Controller',
refs: [
{ ref: 'productOptionsTree', selector: 'product-configurator-settings-window product-options-tree' }
],
init:function () {
var me = this;
me.mainWindow = me.createMainWindow();
me.addControls();
me.callParent(arguments);
return me.mainWindow;
},
addControls: function() {
var me = this;
me.control({
'product-configurator-settings-window product-options-tree': {
addProductOption: me.onAddProductOption
}
});
},
createMainWindow: function() {
var me = this,
window = me.getView('Window').create({
treeStore: Ext.create('Shopware.apps.CCBConfigurablePhotoProductsManager.store.ProductOptionsList').load()
}).show();
return window;
},
onAddProductOption: function() {
var me = this,
optionsTree = me.getProductOptionsTree(),
parentNode = optionsTree.getRootNode(),
nodeCount = parentNode.childNodes.length + 1,
productOption = Ext.create('Shopware.apps.CCBConfigurablePhotoProductsManager.model.ProductOption', {
parent: 0,
type: 0,
title: Ext.String.format('{s name="group/default_name"}New Group [0]{/s}', optionsTree.getRootNode().childNodes.length + 1),
active: true,
leaf: false
});
productOption.setDirty();
parentNode.appendChild(productOption);
optionsTree.getStore().sync(); // Nothing arrives at DB
optionsTree.expandAll();
},
// ...
view/window.js
Ext.define('Shopware.apps.CCBConfigurablePhotoProductsManager.view.Window', {
extend:'Enlight.app.Window',
cls:Ext.baseCSSPrefix + 'product-configurator-settings-window',
alias:'widget.product-configurator-settings-window',
border:false,
autoShow:true,
maximizable:true,
minimizable:true,
layout: {
type: 'hbox',
align: 'stretch'
},
width: 700,
height: 400,
initComponent:function () {
var me = this;
me.createItems();
me.title = '{s name=window/title}Configurator Settings{/s}';
me.callParent(arguments);
},
createItems: function() {
var me = this;
me.items = [
me.createProductOptionsTree()
];
},
createProductOptionsTree: function() {
var me = this;
return Ext.create('Shopware.apps.CCBConfigurablePhotoProductsManager.view.ProductOptions', {
store: me.treeStore,
width: '20%',
flex: 1
});
}
});
store/product_options_list.js
Ext.define('Shopware.apps.CCBConfigurablePhotoProductsManager.store.ProductOptionsList', {
extend: 'Ext.data.TreeStore',
pageSize: 30,
autoLoad: false,
remoteSort: true,
remoteFilter: true,
model : 'Shopware.apps.CCBConfigurablePhotoProductsManager.model.ProductOption',
proxy:{
type:'ajax',
url:'{url controller="CCBConfigurablePhotoProductsManager" action="getProductOptionsList"}',
reader:{
type:'json',
root:'data',
totalProperty:'total'
}
}
});
model/product_option.js
Ext.define('Shopware.apps.CCBConfigurablePhotoProductsManager.model.ProductOption', {
extend : 'Ext.data.Model',
fields : [
{ name : 'id', type : 'int', useNull: true },
{ name : 'parent', type : 'int' },
{ name : 'title', type : 'string' },
{ name : 'active', type: 'boolean' },
{ name : 'type', type : 'int' }
],
idProperty : 'id',
proxy : {
type : 'ajax',
api: {
create: '{url controller="CCBConfigurablePhotoProductsManager" action="createProductOption"}',
update: '{url controller="CCBConfigurablePhotoProductsManager" action="updateProductOption"}',
destroy: '{url controller="CCBConfigurablePhotoProductsManager" action="deleteProductOption"}'
},
reader : {
type : 'json',
root : 'data',
totalProperty: 'total'
}
}
});
php/controller.php
<?php
use Shopware\CustomModels\CCB\ProductOption;
class Shopware_Controllers_Backend_CCBConfigurablePhotoProductsManager extends Shopware_Controllers_Backend_ExtJs
{
public function createProductOptionAction()
{
// Never being called
file_put_contents('~/test.log', "createProductOptionAction\n", FILE_APPEND);
$this->View()->assign(
$this->saveProductOption($this->Request()->getParams())
);
}
public function getProductOptionsListAction()
{
// Works fine
file_put_contents('~/test.log', "getProductOptionsListAction\n", FILE_APPEND);
// ...
}
// ...
EDIT 1
I tried adding a writer for both, the store and the model, as suggested by Saki. But unfortunately it still doesn't work. The createProductOptionAction() in the PHP controller is never being called.
Ext.define('Shopware.apps.CCBConfigurablePhotoProductsManager.model.ProductOption', {
extend : 'Ext.data.Model',
fields : [
{ name : 'id', type : 'int', useNull: true },
{ name : 'parent', type : 'int' },
{ name : 'title', type : 'string' },
{ name : 'active', type: 'boolean' },
{ name : 'type', type : 'int' }
],
idProperty : 'id',
proxy : {
type: 'ajax',
api: {
create: '{url controller="CCBConfigurablePhotoProductsManager" action="createProductOption"}',
update: '{url controller="CCBConfigurablePhotoProductsManager" action="updateProductOption"}',
destroy: '{url controller="CCBConfigurablePhotoProductsManager" action="deleteProductOption"}'
},
reader: {
type : 'json',
root : 'data',
totalProperty: 'total'
},
writer: {
type: 'json'
}
}
});
What I'm wondering tho, the original plugin had no writer implemented. But when adding an entry it immediately appeared in the database.
EDIT 2
I added several listeners to the store.ProductOptionsList:
Ext.define('Shopware.apps.CCBConfigurablePhotoProductsManager.store.ProductOptionsList', {
extend: 'Ext.data.TreeStore',
pageSize: 30,
autoLoad: false,
remoteSort: true,
remoteFilter: true,
model : 'Shopware.apps.CCBConfigurablePhotoProductsManager.model.ProductOption',
root: {
text: 'Product Options',
id: 'productOptions',
expanded: true
},
proxy:{
type: 'ajax',
url: '{url controller="CCBConfigurablePhotoProductsManager" action="getProductOptionsList"}',
reader: {
type:'json',
root:'data',
totalProperty:'total'
}
},
listeners: {
add: function(store, records, index, eOpts) {
console.log("**** Add fired");
console.log(records);
},
append: function(store, node, index, eOpts) {
console.log("**** Append fired");
console.log(node);
},
beforesync: function(operations) {
console.log("**** Beforesync fired");
console.log(operations);
}
}
});
All these Events are getting fired. The beforesync event shows
**** Beforesync fired
Object {create: Array[1]}
create: Array[1]
...
But still, the API requests of the model.ProductOption are not getting fired. It should work. Shouldn't it? Maybe this is a bug in ExtJS 4.1? Or something with Shopware + ExtJS?
EDIT 3
Ok, this is really getting weird.
I added a "write"-Listener to the TreeStore.
write: function(store, operation, opts){
console.log("**** Write fired");
console.log(operation);
Ext.each(operation.records, function(record){
console.log("**** ...");
if (record.dirty) {
console.log("**** Commiting dirty record");
record.commit();
}
});
}
After adding a Node and calling .getStore().sync(), the write-event IS fired, he iterates operation.records, finds one record (the one I just added)... but it isn't dirty, even though I do productOption.setDirty() before adding it to the Tree?!
Thanks alot for your time! :)
A little note on your code:
There is an error in the beforesync event: the function must return true, else sync() will not get fired.
I don't think this is the only problem. Since ExtJs is usually extensive code, I cannot tell you what is the reason of your problem. All I can give, is a simple working example with some explanations.
I'm following the recommended MVC layout, i.e. one file for each class. Here is the complete code:
Ext.define('Sandbox.Application', {
name: 'Sandbox',
extend: 'Ext.app.Application',
controllers: [
'Sandbox.controller.Trees'
]
});
Ext.define('Sandbox.controller.Trees', {
extend: 'Ext.app.Controller',
requires: ['Ext.tree.*', 'Ext.data.*', 'Ext.grid.*'],
models: ['TreeTest'],
stores: ['TreeTest'],
views: ['TreeGrid'],
init: function(){
this.control({
'treegrid toolbar button#addchild': {click: this.onAddChild},
'treegrid toolbar button#removenode': {click: this.onRemoveNode}
})
},
onAddChild: function(el){
var grid = el.up('treepanel'),
sel = grid.getSelectionModel().getSelection()[0],
store = grid.getStore();
store.suspendAutoSync()
var child = sel.appendChild({task: '', user: '', leaf: true});
sel.set('leaf', false)
sel.expand()
grid.getView().editingPlugin.startEdit(child);
store.resumeAutoSync();
},
onRemoveNode: function(el){
var grid = el.up('treepanel'),
sel = grid.getSelectionModel().getSelection()[0];
sel.remove()
}
});
Ext.define('Sandbox.model.TreeTest', {
extend: 'Ext.data.TreeModel',
fields: [
{name: 'id', type: 'int'},
{name: 'task', type: 'string'},
{name: 'user', type: 'string'},
{name: 'index', type: 'int'},
{name: 'parentId', type: 'int'},
{name: 'leaf', type: 'boolean', persist: false}
]
});
Ext.define('Sandbox.store.TreeTest', {
extend: 'Ext.data.TreeStore',
model: 'Sandbox.model.TreeTest',
proxy: {
type: 'ajax',
url: 'resources/treedata.php',
api: {
create: 'resources/treedata.php?action=create',
read: undefined,
update: 'resources/treedata.php?action=update',
destroy: 'resources/treedata.php?action=destroy'
}
},
autoSync: true,
autoLoad: false,
root: {id: 1, text: "Root Node", expanded: false}
});
Ext.define('Sandbox.view.TreeGrid', {
extend: 'Ext.tree.Panel',
alias: 'widget.treegrid',
store: 'TreeTest',
columns: [{
xtype: 'treecolumn',
text: 'Task',
flex: 2,
sortable: true,
dataIndex: 'task',
editor: {xtype: 'textfield', allowBlank: false}
},{
dataIndex: 'id',
align: 'right',
text: 'Id'
}, {
dataIndex: 'user',
flex: 1,
text: 'Utilisateur',
editor: {xtype: 'textfield', allowBlank: false}
}],
plugins: [{
ptype: 'rowediting',
clicksToMoveEditor: 1,
autoCancel: false
}],
viewConfig: {
plugins: [{
ptype: 'treeviewdragdrop',
containerScroll: true
}]
},
tbar:[
{xtype: 'button', text: 'Add Child', itemId: 'addchild'},
{xtype: 'button', text: 'Remove', itemId: 'removenode'}
]
});
I didn't elaborate the server side code. I just copied the Kitchensink example code. To get to work a create, update or delete request, it has to return the modified rows along with success: true.
Explanations:
I needed to launch sencha app build after adding the required classes in order to display everything correctly
file model/TreeTest.js : the field index is required if we want a reorder to be saved back to the server. If it is ommitted, only rows with edited fields are saved back. It was necessary to add persist: false for the leaf field, because this data is not needed on the server.
file store/TreeTest.js :
autoSync: true worked out of the box, with the restriction mentionned on reordering.
the tree autoLoads when the root node is expanded: true or if autoLoad: true. If we don't want to autoLoad, autoLoad and expanded must be both false.
root is required for a good working store. If it is missing, we must load the store manually, even if autoLoad: true.
It was necessary to add the api configuration. Without it, it was not possible to tell appart an update, create and delete request.
file view/TreeGrid.js :
a column with xtype: 'treecolumn' is required.
The removal of a row is simple and syncs the store automatically. The server side is responsible for deleting children if there are.
The creation of a new row is trickier, because the store is sync()'d as soon as appendChild() is called (suspendAutoSync() is used to avoid to write the new child before it is edited). Also, the grid gets only updated, if we control the leaf property manually (.set('leaf', false)). I expect ExtJs to correctly manage the leaf property and consider this as a bug.
The proxy used by the store must have a writer configured for sync operations to talk to the server.
Good day,
I'm pretty new in extjs 5 and mvvm. I want to make an ajax request in order to display a treepanel with datas caught with a php.
Here is my store
Ext.define('MyApp.store.servicesStore', {
extend: 'Ext.data.TreeStore',
// alias: 'store.servicesStore',
storeId : 'servicesStore',
model : 'MyApp.model.servicesModel',
proxy: {
type: 'ajax',
url: 'app/store/data/GetServices.php'
},
root: {
text: 'Events',
id: 'root'
},
autoLoad: true,
folderSort: true
});
I've seen that a "success" can resolve that issue but I don't need a succes as it's only displayed in a treePanel
Ext.define('MyApp.view.tabServices.servicesTab', {
extend: 'Ext.tree.Panel',
xtype: 'servicesTab',
layout: {
type: 'border'
},
useArrows: true,
rootVisible: false,
store: {type: 'servicesStore'},
forceFit: true,
columns: [{
xtype: 'treecolumn',
dataIndex: 'text',
width: 600
}, {
dataIndex: 'mbt',
cls: 'mbtcss',
width: 80
}, {
dataIndex: 'bt',
cls: 'btcss',
width: 75
}, {
dataIndex: 'details', // port separated from rest
width: 60
}, {
dataIndex: 'code',
width: 80
}]
});
So, when I launch my app, the "You're trying to decode an invalid JSON String" appears, how can I do to make it understand that I actually use a php file?
More precisely, that code is working in extjs 3.4
To run the PHP code which did work under ExtJS 4 you must either modify your PHP to return the data in JSON format. Or otherwise you set your "enable compatibility" to version 4.
See "Enabling Compatibility" under http://docs.sencha.com/extjs/5.0/whats_new/5.0/extjs_upgrade_guide.html#Enabling_Compatibility.
compatibility: {
ext: '4.2'
}
I've such a simple question but can't find answer (documentation) on it. I've created Grid , where information is retrieved from MySQL database. Using Ext JS 4.2 .
Let's take a look of script ...
Ext.define("AppStore",{
extend: "Ext.data.Model",
fields: [
{name: "nickname" , type: "auto"},
{name: "email" , type: "auto"}
]
});
var store = Ext.create("Ext.data.Store",{
model: "AppStore",
proxy: {
type: "ajax",
api: {
read : "./read.php",
update : "./update.php"
},
reader: {
type: "json",
root: ""
},
writer: {
type: "json",
writeAllFields: true,
encode: false,
root: ""
}
},
listeners: {
read: function(operation, callback, scope){
},
update: function(operation, callback, scope){
// Do I have to do something from here ?
}
},
autoLoad: true
});
Ext.create("Ext.grid.Panel",{
store: store,
selMode: "cellmodel",
columns: [
{
text: "Nickname",
flex: 1,
dataIndex: "nickname",
editor: {
xtype: "textfield",
allowBlank: false
}
},
{
text: "Email",
flex: 1.5,
dataIndex: "email",
editor: {
xtype: "textfield",
allowBlank: false
}
}
],
plugins: [
Ext.create("Ext.grid.plugin.CellEditing",{
clicksToEdit: 2
})
]
});
Everything is working fine , just interested in how I have to send request to MySQL for updating data after changing it in Grid cell . Any example , documentation or the way how to accomplish this task will be appreciated , thanks ...
Typically, you'll want to call sync() on your grid's store in order to persist the model changes to the server. This can be configured to occur automatically on every edit (see the autoSync property of the store). However, I would suggest it's better to handle the sync() call based on some specific action (e.g., a "Save" button being clicked, etc.).
JqGrid documentation states the following regarding postData:
an array used to add content to the data posted to the server
And that's it. So, I'm using postData to send a variable to my PHP so that I can use a switch case to call the function I want.
This allows me to have a single PHP page containing all the functions for my project. I want to do the same thing with editData so I don't need a PHP page for every inline editing function associated with the project.
However, editData doesn't seem to be passing to the PHP page. I tried printing the POSTed variables to a file and they were empty. Suggestions?
Note: I am aware of the editData bug, but this should have been fixed by version 4.4.4 which is the one I'm using
$("#list").jqGrid({
url:'functions.php',
datatype:'xml',
mtype:'POST',
postData: {
action:'popGrid',
sqlCount:sqlCount,
sqlSelect:sqlSelect,
sqlSelect2:sqlSelect2,
label1:label1,
label2:label2,
},
colNames:['Label','Account_Num','Amount', 'Type Code', 'Record Code', 'Sequence'],
colModel :[
{name:'label', index:'label', width:150, align:'center', sortable:false, editable:true},
{name:'cntrct_id', index:'cntrct_id', width:150, align:'center', sortable:true},
{name:'amount', index:'amount', width:150, align:'center', sortable:false, editable:true},
{name:'type_cd', index:'type_cd', width:150, align:'center', sortable:false, editable:true},
{name:'rec_cd', index:'rec_cd', width:150, align:'center', sortable:false},
{name:'db_seq', index:'db_seq', width:150, align:'center', sortable:false},
],
editurl: 'functions.php',
extraparam: { action: function(){ return 'grdAdjust'; } },
onSelectRow: function(id) {
if(id && id!==lastSel) {
jQuery('#list').restoreRow(lastSel);
jQuery('#list').editRow(id,true);
lastSel=id;
}
},
pager: '#pager',
rowNum:100,
rowList:[100,200,300,400,500,600,700,800,900,1000],
sortname: 'cntrct_id',
sortorder: 'desc',
viewrecords: true,
caption: 'Adjustments'
});
The option editData play the same role in form editing as postData in the main grid. On the other side you wrote about "inline editing" in the text of your question. In the case you should use extraparam option instead (see the documentation). If you need to have common options of inline editing then probably the usage defalut settings in $.jgrid.inlineEdit could be helpful for you. You don't posted any code and I am not sure which editing mode and in which way you use, so I can't include more examples of usage editData, extraparam etc.
UPDATED: You use extraparam in a wrong way now. extraparam is not jqGrid option, it's option of editRow. Correct usage could be about the following:
onSelectRow: function (id) {
if (id && id !== lastSel){
$(this).jqGrid("restoreRow", lastSel);
$(this).jqGrid("editRow", id, {
keys: true,
extraparam: {
action: function () {
return 'grdAdjust';
}
}
});
lastSel = id;
}
}
If you need post constant value of action you can use simplified form of extraparam: like extraparam: {action: 'grdAdjust'}. The usage of functions is really helpful if you need return the value of some variable or some element from the page which will be changed between different calls of editRow.
Additionally I would recommend you to include gridview: true option of jqGrid and to simplify colModel which you use. If index has the same value as name you can emit it. The default value of width is already 150, so you don't need specify width:150 too. If you want use align:'center' in all or in the most columns you can change the default value of align for the grid by including cmTemplate: {align:'center'} option in the grid. Because the most column has sortable: false you can include the setting in the cmTemplate too. As the result you can reduce colModel to the following:
colModel: [
{name: 'label', editable: true},
{name: 'cntrct_id', sortable: true},
{name: 'amount', editable: true},
{name: 'type_cd', editable: true},
{name: 'rec_cd'},
{name: 'db_seq'},
],
cmTemplate: {align: 'center', sortable: false},
Such changes simplify the code not only for reading, but for maintain too. See here more information about column templates.
I have one JQGrid in my php file and I have placed inside one form . On submitting form, i just want the checked value from the JQGrid.
<script type="text/javascript">
$(function() {
$("#list1").jqGrid({
url:'revMemberJson.php',
datatype: 'json',
mtype: 'GET',
loadonce: true,
// jsonReader: { repeatitems: false },
colNames:['Name','Mobile'],
colModel :[
{name:'name', index:'name',width: 100,searchoptions: { sopt: ['eq', 'ne','cn']}},
{name:'mobile', index:'mobile',search: false,width: 120}
],
pager: '#pager',
rowNum: 5,
rowList:[5,20,30],
rownumbers: true,
multiselect:true,
sortname: 'id',
sortorder: 'desc',
viewrecords: true,
height: 'auto',
width: 420,
shrinkToFit: false,
gridview: true,
caption: 'Members'
});
jQuery("#list1").jqGrid('navGrid','#pager',{edit:false,add:false,del:false});
});
var myGrid = $('#list1'),
selRowId = myGrid.jqGrid ('getGridParam', 'selrow'),
celValue = myGrid.jqGrid ('getCell', selRowId, 'mobile');
</script>
And I have used the following code to get the checked value , But All stuff are made in java script. But I have to get the values for updating the database. So i need to get the value by post.
Please provide me the methods..
You should use
var selRowIds = myGrid.jqGrid ('getGridParam', 'selarrrow');
insteda of
var selRowId = myGrid.jqGrid ('getGridParam', 'selrow');
to get the array with ids of selected rows. You can use JSON.stringify(selRowIds) or selRowIds.join(',') to convert array in the form which you can easy send to the server.
I think that you can find some additional information in the answer (see the demo).