I'm stuck in the development of an extension for Shopware.
I want to extend the administration of categories in the correct way.
To achieve that created plugin (legacy). This plugins appends the first tab within a category.
//{block name="backend/category/view/tabs/settings" append}
This is done to add a fieldset with a dropdown. The file looks like this:
//{block name="backend/category/view/tabs/settings" append}
Ext.define('Shopware.apps.HaendlerbundFoobarCategories.view.category.tabs.settings', {
override:'Shopware.apps.Category.view.category.tabs.Settings',
getItems: function() {
var me = this;
var items = me.callParent(arguments);
me.FooBar = me.getFooBarSection();
items.push(me.FooBar);
return items;
},
getFooBarSection : function()
{
var me = this;
return Ext.create('Ext.form.FieldSet',{
title: 'FooBar Verlinkung',
anchor: '100%',
defaults : me.defaults,
disabled : false,
items : me.getDropdowns()
});
},
getDropdowns:function(){
var me = this;
return me.templateComboBox = Ext.create('Ext.form.field.ComboBox', {
xtype:'combobox',
fieldLabel: 'FooBar Product',
store: me.fooBarProducts.load(),
labelWidth: 155,
valueField: 'id',
displayField:'title',
editable: true,
allowBlank:true,
name:'fbproduct'
});
}
});
//{/block}
The main problem I suspect is the store. Leaving it like this I get an JS
error Cannot read property 'load' of undefined. without the .load() there is no error, but I also can't determine if the store got loaded.
The store file itself is in Views/backend/haendlerbund_foobar_categories/store/foo_bar_products
and the content of the file is:
//{block name="backend/haendlerbund_foobar_categories/store/fooBarProducts"}
Ext.define('Shopware.apps.HaendlerbundFoobarCategories.store.fooBarProducts', {
//...
model: 'Shopware.apps.HaendlerbundFoobarCategories.model.fooBarProducts',
proxy : {
type : 'ajax',
/**
* Configure the url mapping for the different
* store operations based on
* #object
*/
api : {
read : '{url controller=HaendlerbundFoobarCategories action=getProducts}'
},
/**
* Configure the data reader
* #object
*/
reader : {
type : 'json',
root: 'data'
}
}
});
//{/block}
EDIT:
For further context, this is the current state of the model the store references.
Ext.define('Shopware.apps.HaendlerbundFoobarCategories.model.fooBarProducts', {
extend: 'Ext.data.Model',
/**
* If the name of the field is 'id' extjs assumes automatically that
* this field is an unique identifier.
* #integer
*/
idProperty : 'id',
fields:[
{ name : 'id', type: 'int' },
{ name : 'ffid', type: 'bigint' },
{ name : 'title', type: 'string' },
{ name : 'description', type: 'string' },
{ name : 'price', type: 'decimal' },
{ name : 'vat', type: 'decimal' },
{ name : 'image', type: 'text' },
{ name : 'active', type: 'boolean' },
{ name : 'createdAt', type: 'datetime' },
{ name : 'modfiedAt', type: 'datetime' }
],
/*associations: [
{
relation: 'OneToMany',
storeClass: 'Shopware.apps.HaendlerbundFoobarCategories.store.fooBarProducts',
loadOnDemand: true,
type: 'hasMany',
model: 'Shopware.apps.HaendlerbundFooBarCategories.model.fooBarProducts',
name: 'getCategories',
associationKey: 'categories'
},
]*/
});
And the php controller which the store references as well has the following content:
<?php
class Shopware_Controllers_Backend_HaendlerbundFoobarCategories extends Shopware_Controllers_Backend_Application
{
protected $model = 'Shopware\CustomModels\Product\FFProduct';
protected $alias = 'ffproducts';
protected function getListQuery()
{
$builder = parent::getListQuery();
return $builder;
}
protected function getDetailQuery($id)
{
$builder = parent::getDetailQuery($id);
return $builder;
}
protected function getAdditionalDetailData(array $data)
{
return $data;
}
public function getProducts(){
$builder = $this->getManager()->createQueryBuilder();
$builder->select('*')
->from($model, $alias);
$data['id'] = 1;
$data['ffid'] = 1;
$data['title'] = 'lorem ipsum';
$this->view()->assign([
'success' => true,
'data' => $data,
'total' => 1
]);
}
}
It should return some dummy data for now.
I fail to solve the problem. As any documentation I was able to find was either focused on creating a separate component of changing an existing field. I suspect that I'm in the wrong scope or have a namespacing error or something.
Any help is greatly appreciated.
Your problem is the store assigning to combobox
this line of code isn't correct:
store: me.fooBarProducts.load(),
Usually a store should be only connected to a combobox like this:
store:'fooBarProducts'
Heres a fiddle to show you:
https://fiddle.sencha.com/#view/editor&fiddle/1kqj
Ext.application({
name : 'Fiddle',
launch : function() {
var yourStore=Ext.create('Ext.data.Store',{
fields:[{
name:'text'
},{
name:'value'
}],
data:[
{text:'test1',value:'testVal1'},
{text:'test2',value:'testVal2'},
{text:'test3',value:'testVal3'}
]
});
Ext.create({
xtype:'window',
width:300,
height:200,
items:[{
xtype:'combo',
displayField:'text',
valueField:'value',
store:yourStore
},{
xtype:'combo',
displayField:'text',
valueField:'value',
store:yourStore
}]
}).show();
}
});
have also a look here: http://docs.sencha.com/extjs/6.2.0/classic/Ext.form.field.ComboBox.html
for a combobox example
and here to store declaration:
http://docs.sencha.com/extjs/6.2.0/modern/Ext.data.Store.html
To load your store, you should call the store load out of combo declaration
If you use
store: somestore.load()
the combobox will bind to the value returned by load. The load function does not return anything, so the combo's store config is set to undefined.
What you want to do may be
me.fooBarProducts.load();
return me.templateComboBox = Ext.create('Ext.form.field.ComboBox', {
xtype:'combobox',
fieldLabel: 'FooBar Product',
store: me.fooBarProducts,
labelWidth: 155,
valueField: 'id',
displayField:'title',
editable: true,
allowBlank:true,
name:'fbproduct'
});
Related
I am trying the get a combox in a grid which select something in the editor function. But the rendering value is 0 each time. After saving it works correctly.
Ext.define('Shopware.apps.Order.view.detail.BackPosition', {
override: 'Shopware.apps.Order.view.detail.Position',
initComponent: function () {
var me = this;
me.mdsupplierStore = Ext.create('Shopware.apps.Order.store.MDSupplier').load();
me.callParent(arguments);
},
getColumns: function(grid) {
var me = this;
var col = me.callOverridden(arguments);
var md_supplier = {};
grid.mdsupplierStore = me.mdsupplierStore;
var MDSupplier= {
header: 'Lieferant',
dataIndex: 'md_supplier',
flex:2,
renderer: me.supplierColumn,
editor: {
xtype: 'combobox',
editable: false,
queryMode: 'local',
allowBlank: false,
store: grid.mdsupplierStore,
displayField: 'name',
valueField: 'id',
}
};
col = Ext.Array.insert(col, 9, [MDSupplier]);
return col;
},
supplierColumn: function(value, metaData, rowRecord) {
var me = this;
console.log(value);
//value is 0 when I click the editor combobox <---
},
});
Model:
Ext.define('Shopware.apps.Order.model.MDSupplier', {
extend:'Shopware.data.Model',
idProperty : 'id',
fields:[
{ name : 'id', type: 'int'},
{ name : 'name', type: 'string'}
]
});
Store:
Ext.define('Shopware.apps.Order.store.MDSupplier',{
configure: function() {
return { controller: 'MDSupplier' };
},
/**
* Define that this component is an extension of the Ext.data.Store
*/
extend: 'Ext.data.Store',
/**
* Auto load the store after the component
* is initialized
* #boolean
*/
autoLoad: false,
/**
* Define the used model for this store
* #string
*/
model: 'Shopware.apps.Order.model.MDSupplier',
proxy : {
type : 'ajax',
url: '/backend/MDSupplier/load',
reader:{
type: 'json',
root: 'data',
totalProperty: 'total'
}
}
});
Can anybody tell me, what am I doing wrong ?
I got it. The processing of the data was wrong, so the field was everytime NULL
I have a grid populating records from view model (Ajax proxy data from Java restful web services). When I select a record in the grid form open and the fields are displayed. The records are editable using the form.
I have one tag field which is binded to a store and I should be able to populate the data associated to the record whenever the user selects a record.
"data" : [ {
"createdOn" : 1475678859000,
"updatedOn" : 1475679885000,
"updatedBy" : null,
"id" : 174,
"userName" : "ffff,
"firstName" : "gg",
"lastName" : "ggg",
"salesDepartment" : [ {
"id" : 3,
"code" : "FC",
"name" : "Fiat-Chrysler",
"departmentHead" : "xxx",
"applicationCode" : null} ],}
I need to bind the value of id from sales department object . how can I achieve this. Please help me.
{xtype: 'tagfield',
anchor: '100%',
reference: 'salesDept',
fieldLabel: 'Sales Dept\'s',
name: 'salesDepartment',
allowBlank: false,
displayField: 'name',
valueField: 'id',
bind: {
value: '{record.salesDepartmentIds}',
store: '{SalesDepartmentStore}'},
}
Tag fields are really only designed to work with arrays or comma separated lists;
It looks like you are trying to use with associations, which it would be nice if there was more support for this out of the box.
I've had a go, and in terms of displaying got it working however saving values will really depend on how you plan to sync values to the server, if you are going to use in built proxies etc. then this will present a whole different challenge. I would like a similar component for my own apps, I will think on this further and may even create a UX for this.
I think you have several issues here, one is getting your associations working properly, then you need to make your tagfield work as expected.
Here is the fiddle
And the key parts are:
An extended tagfield:
Ext.define('RelatedTagField', {
extend: 'Ext.form.field.Tag',
xtype: 'rtagfield',
config: {
relatedStore: null
},
setValue: function (val) {
this.setRelatedStore(val);
var value;
if (val && val.isStore) {
value = val.collect('id');
} else {
value = '';
}
this.callParent([value]);
},
getValue: function () {
return this.relatedStore;
},
onBindStore: function () {
this.callParent(arguments);
this.on('select', function (tagfield, selection) {
var selectedIds = [];
//add any new selections
Ext.each(selection, function (rec) {
var rrec = this.relatedStore.getById(rec.id);
if (!rrec) {
this.relatedStore.add(rec.data)
}
selectedIds.push(rec.id);
}, this);
//remove any not selected anymore
this.relatedStore.each(function (rrec) {
if (selectedIds.indexOf(rrec.id) == -1) {
this.relatedStore.remove(rrec);
}
}, this);
}, this);
},
})
Binding the value:
{
xtype: 'rtagfield',
fieldLabel: 'Sales Department',
name: 'id',
displayField: 'name',
valueField: 'id',
bind: {
store: '{salesDepartment}',
value: '{record.salesDepartment}'
}
},
And adding a definition for the association:
Ext.define('MyApp.model.User', {
extend: 'Ext.data.Model',
alias: 'model.user',
hasMany: [{
model: 'MyApp.model.SalesDepartmentModel',
associationKey: 'salesDepartment',
role: 'salesDepartment'
}],
requires: [
'Ext.data.field.String'
],
fields: [{
type: 'string',
name: 'userName'
}, {
type: 'string',
name: 'firstName'
}, {
type: 'string',
name: 'lastName'
}, {
name: 'salesDepartment'
}, {
name: 'roles'
}, {
type: 'string',
name: 'email'
}, {
name: 'notificationFrequencyId'
}]
});
Further reading
I suggest you read more on associations and the tagfield source code
In terms of saving records back to the server, I would recommend looking at sessions
In my store I have a field called CreditName. In my view I am trying to check if CreditName is not null and if it is not enter it into my filefield. I have added a listener to my filefield that will enter text into the filefield. What I am having trouble with is getting CreditName into the filefield. I know that it is reading from my store because other fields are appearing properly.
Here is my code for my filefield
xtype: 'filefield',
buttonText: 'Select A File',
fieldLabel: 'File',
name: 'Credit',
labelWidth: 50,
msgTarget: 'under',
return true;
},
listeners: {
render: function (comp) {
comp.setRawValue(CreditName);
}
}
Here is the store code
fields: [ {
name: 'PartyId',
type: 'string'
}, {
name: 'CreditName',
type: 'string',
critical: true
}],
proxy: {
type: 'ajax',
url: 'api/parties',
reader: {
type: 'json'
}
}
PartyId shows up fine, here is the code for that, it is in the same view as filefield
{
xtype: 'displayfield',
name: 'PartyId',
fieldLabel: ' Party ID'
},
In your config of 'filefield', you have to use same name as 'name' property in store. In your case, it should be name: 'CreditName', not 'Credit'.
--edit--
You can get model values in 'render' listener like this:
render: function (comp) {
var model = comp.getModelData(),
value = model.get('CreditName');
comp.setRawValue(value);
}
I am using Bancha basic version for my site. I want to show data from emplyees table to grid using Ext JS.
Following is the code for controller:
class EmployeesController extends AppController {
/**
* #banchaRemotable
*/
public function getData(){
return $this->Employee->find('all');
}
}
Following is my JavaScript file:
Ext.application({
name: 'BanchaExample',
launch: function() {
/**
* Example 1
* Create a grid panel which provides full CRUD support
*/
Bancha.getStub('Employee').index(function(result){
Ext.define('Employee', {
extend: 'Ext.data.Model',
fields: [ 'id', 'name' ]
});
var myStore = Ext.create('Ext.data.Store', {
model: 'Employee',
data: result.data
});
Ext.create('Ext.grid.Panel', {
renderTo: Ext.getBody(),
model: 'Employee',
width: 400,
height: 200,
title: 'Application Users',
//scaffold: 'MyApp.model.User'
columns: [
{
header: 'id',
width: 100,
ryinsortable: false,
hideable: false,
dataIndex: 'id'
},
{
header: 'name',
width: 150,
dataIndex: 'name'
}
]
});
});
}
});
It gives me following response in my console:
[{"type":"rpc","tid":1,"action":"Employee","method":"read","result":{"success":true,"data":[{"Employee":{"id":"1","name":"test"}},{"Employee":{"id":"2","name":"tese"}}],"message":"Expected the response to be multiple Employee records, but some records were missing data, so did not convert data into Ext JS/Sencha Touch structure."}}]
Only grid with header is displayed. Data is not displayed.
Please help me to solve this.
I don't work with Bancha, but may be this will help.
I don't see any grid connection with store. Also store need some config(reader) to parse your result. 'data' is normally used for inline static data.
Ext.define('Employee', {
extend : 'Ext.data.Model',
fields : [ {
name : 'id',
mapping : 'Employee.id'
}, {
name : 'name',
mapping : 'Employee.name'
} ]
});
var myStore = Ext.create('Ext.data.Store', {
model : 'Employee',
proxy : {
url : 'SPECIFY URL TO YOUR SERVICE',
type : 'ajax',
reader : {
type : 'json',
root : 'result.data'
}
}
});
also add store to grid and you can remove model in grid
Ext.create('Ext.grid.Panel', {
renderTo: Ext.getBody(),
store : myStore,
...
});
Bancha Basic does not automatically transform records from the CakePHP structure to Ext JS. For what you want to do you need to use Bancha Pro.
If you want to use Bancha Basic you need to return a correct Ext JS data array.
I have a combo with a remote store in the modal window. To obtain the data is necessary to send an extra parameter to the store. This parameter is stored as a property of the window. How can I pass it?
This is my app.js file (I use MVC model, atleast try to use it :) ):
Ext.application( {
requires: [
'Ext.Ajax'
],
autoCreateViewport: true,
name: 'PM',
stores: [
...
'SourceIps',
...
],
models: [
...
],
controllers: [
...
],
init: function() {
}
} );
How I show window:
showAddRProbe: function () {
var data = {
'deviceId': this.getProbesDeviceCombo().getValue()
};
var addProbe = Ext.create( 'PM.view.AddProbe', [true, data] );
addProbe.show();
}
Window:
Ext.define( 'PM.view.AddProbe', {
extend: 'Ext.window.Window',
...
constructor: function( data ) {
this.newProbe = data[0];
this.probeData = data[1];
...
Required parameter passed as probeData.data.deviceId
Combo:
{
xtype: 'combo',
allowBlank: false,
blankText: Locale.gettext( 'Please select a Source IP' ),
fieldLabel: Locale.gettext( 'Source IP' ),
name: 'sourceIP',
triggerAction: 'all',
store: 'SourceIps',
value: Ext.getStore( 'SourceIps' ).getAt(0).get('id'),
valueField: 'id',
displayField: 'name',
queryMode: 'local'
}
Store:
Ext.define('PM.store.SourceIps', {
extend: 'Ext.data.Store',
model: 'PM.model.IdName',
autoLoad: true,
proxy: {
type: 'ajax',
api: {
read: 'data/getDeviceIps.php'
},
reader: {
type: 'json',
root: 'data',
successProperty: 'success',
messageProperty: 'message'
}
}
});
I tired to add extraParam as follow, but it does not work:
var probeData = this.getProbeWindow().probeData.data;
this.getSourceIpCombo().getStore().getProxy().setExtraParam( 'deviceId', probeData.deviceId );
this.getSourceIpCombo().getStore().load();
Use
this.getSourceIpCombo().getStore().load({
params: {
deviceId : probeData.deviceId
}
});
You could add storeId property to your store and then use
var store = Ext.data.StoreManager.lookup('myStore');
and use this to apply extra params:
Ext.apply(store.getProxy().extraParams, {
foo : 'bar',
...
});
or
store.getProxy().setExtraParam("countriesId", 1) // add parameter 'countriesId' = 1