Unable to Validate Field in Shopware Backend Form - plugins

I am trying to validate a field in my ExtJs file by sending a hit to my controller.. all works fine and I get the result back.. but the problem is that I am unable to get the me.article in the code as it shows undefined so my logic in the controller does not return the result as expected.
Any help would be highly appreciated.
Note: this only happens for Shopware v.5.4.6. It works fine for Shopware 5.2.
Shopware.apps.Article.view.detail.Base.prototype.createLeftElements = function() {
var me =this, articleId = null, additionalText = null;
console.log('article', me.article);
if (me.article instanceof Ext.data.Model && me.article.getMainDetail().first() instanceof Ext.data.Model) {
articleId = me.article.getMainDetail().first().get('id');
additionalText = me.article.getMainDetail().first().get('additionalText');
}
me.nameField = Ext.create('Ext.form.field.Text', {
name: 'name',
dataIndex: 'name',
fieldLabel: me.snippets.name,
allowBlank: false,
enableKeyEvents:true,
checkChangeBuffer:700,
labelWidth: 155,
anchor: '100%',
vtype:'remote',
validationUrl: '{url controller="MyController" action="check"}',
validationRequestParam: articleId,
validationErrorMsg: '{s name=detail/base/number_validation}Validation Message.{/s}'
});
// .. some code here which is irrelevant
return [
me.supplierCombo,
me.nameField,
me.mainDetailAdditionalText,
me.numberField,
{
xtype: 'checkbox',
name: 'active',
fieldLabel: me.snippets.active,
inputValue: true,
uncheckedValue:false
},
{
xtype: 'checkbox',
name: 'isConfigurator',
fieldLabel: me.snippets.configurator.fieldLabel,
inputValue: true,
uncheckedValue:false
}
];
};

I am not that deep into ExtJS, but perhaps the CSRF-protection causes this problem? Perhaps you need to whitelist your controller.
https://developers.shopware.com/developers-guide/csrf-protection/#addition-to-backend-token-validation

Related

Why is my page not rendering EnhancedGrid

Good day to all, while studying dojo, I ran into a problem that I do not draw an EnhancedGrid on my page. this error appears in the browser console:
dojo.js.uncompressed.js:1321 Uncaught TypeError: Cannot read property 'get' of null
at Object.getFeatures (ObjectStore.js.uncompressed.js:241)
at Object._setStore (DataGrid.js.uncompressed.js:14511)
at Object.advice (dojo.js.uncompressed.js:8428)
at Object.c [as _setStore] (dojo.js.uncompressed.js:8408)
at Object.postCreate (DataGrid.js.uncompressed.js:14351)
at Object.l (dojo.js.uncompressed.js:10753)
at Object.postCreate (EnhancedGrid.js.uncompressed.js:90)
at Object.create (DataGrid.js.uncompressed.js:4330)
at Object.postscript (DataGrid.js.uncompressed.js:4243)
at new <anonymous> (dojo.js.uncompressed.js:10950)
the grid drawing script looks like this:
var blogStore;
/**
* Creates Dojo Store.
*/
require(["dojo/store/JsonRest",
"dojo/data/ObjectStore"
], function (JsonRest, ObjectStore) {
blogJsonStore = new JsonRest({
handleAs: 'json',
target: 'http://localhost:8080/myservice'
});
var data = {
identifier: 'id',
items: []
};
blogJsonStore.query({
start: 0,
count: 10
}).then(function (results) {
var res =[];
res = results;
if (0 === res.length){
data.items.push("There are no entries in this blog. Create a post!!!")
}else {
data.items.push(results)
}
});
blogStore = new ObjectStore({data: data});
});
/**
* Creates Dojo EnhancedGrid.
*/
require(["dojox/grid/EnhancedGrid",
"dojox/grid/enhanced/plugins/Filter",
"dojox/grid/enhanced/plugins/NestedSorting",
"dojox/grid/enhanced/plugins/Pagination",
"dojo/domReady!"
], function (EnhancedGrid) {
Grid = new EnhancedGrid({
id: 'grid',
store: blogStore,
structure: [
{ name: 'Message', field: 'text', datatype: 'string',
width: 'auto', autoComplete: true }
],
rowsPerPage: 5,
rowSelector: "20px",
selectionMode: "single",
plugins: {
nestedSorting: true,
pagination: {
description: true,
pageStepper: true,
sizeSwitch: true,
pageSizes: ["5","10","15","All"],
maxPageStep: 4,
position: "bottom"
}
}
});
Grid.placeAt('resultDiv');
Grid.startup();
});
if you remove the blog "Creates Dojo Store." it renders normally
Help me solve the problem. Thank you in advance for any help

ExtJS MultiSelect Edit - Not working for multi value selection

I have a GridEditPanel where the 1st column is a combobox with multiSelect. The values are being loaded correctly from the DB and is being written in the DB correctly as well. In the event where the the combobox has a single value, the drop-down highlights the value correctly as well.
The issue is when the combobox has multiple values, it displays the values correctly, however during edit the multiple values are not selected.
Model:
extend: 'Ext.data.Model',
idProperty: 'contactTypeID',
fields: [
{
name: 'contactTypeID',
type: 'string'
},
{
name: 'contactType',
type: 'string'
}
],
View GridEditPanel
emptyText: "There are no contacts.",
insertErrorText: 'Please finish editing the current contact before inserting a new record',
addButtonText: 'Add Contact',
itemId: 'contacts',
viewConfig: {
deferEmptyText: false
},
minHeight: 130,
initComponent: function () {
var me = this,
contactTypes;
// Creating store to be referenced by column renderer
contactTypes = Ext.create('Ext.data.Store', {
model: '********',
autoLoad: true,
listeners: {
load: function () {
me.getView().refresh();
}
}
});
this.columns = [
{
text: 'Contact Role',
dataIndex: 'contactRoleID',
flex: 1,
renderer: function (value) {
// Lookup contact type to get display value
//If a contact has multiple roles, use split by ',' to find display values.
if (value.includes(',')) {
var a = value.split(','), i, contTypeIds = [];
var contTypes = new Array();
for (i = 0; i < a.length; i++) {
contTypeIds.push(a[i]);
contTypes.push(contactTypes.findRecord('contactTypeID', a[i], 0, false, false, true).get('contactType'));
}
console.log('Multi Render Return Value: ' + contTypes);
return contTypes;
}
else {//if not a contact will only have one role.
var rec = contactTypes.findRecord('contactTypeID', value, 0, false, false, true); // exact match
console.log('Single Render Return Value: ' + rec.get('contactType'));
return rec ? rec.get('contactType') : '<span class="colselecttext">Required</span>';
}
},
align: 'center',
autoSizeColumn: true,
editor: {
xtype: 'combobox',
store: contactTypes,
multiSelect: true,
delimiter: ',',
forceSelection: true,
queryMode: 'local',
displayField: 'contactType',
valueField: 'contactTypeID',
allowBlank: false
}
},
I cannot see the model of GridEditPanel, but I assume you are using the wrong field type, string instead of array (Have a look at the converter function, maybe it will help you to fix the problem). I wrote a small post in my blog about multiSelect combobox editor in editable grid. The sample works with v4.2
Hope it will help you to fix the bug.

Sencha ExtJS RESTful grid example confusion

I am very confused by the Sencha documentation for ExtJS. The documentation begins with a Getting Started guide which highlights and illustrates the importance on a suitable structure for the classes and source code of your application. But the provided examples then break all the conventions laid down by the Getting Started guide. Instead of code being broken down into appropriate Model, Store, View, etc. class files the examples are provided as a single file with example source code which is not easily re-usable in separate source files.
I started by following the Portal example (http://docs.sencha.com/ext-js/4-1/#!/example/portal/portal.html) as this is the sort of application I want to create. I wanted to enhance the Portal example and add in a screen which would display a grid and use a RESTful web service as the data backend. I have created the backend I just want to create the front-end. So I looked at the RESTful example (http://docs.sencha.com/ext-js/4-1/#!/example/restful/restful.html)
I have tried to copy the RESTful example into the recommended pattern of seperate classes e.g. Model, Store, View:
Model:
Ext.define('MyLodge.model.Member', {
extend: 'Ext.data.Model',
fields: [
{name: 'name', type: 'string'},
{name: 'email', type: 'string'},
{name: 'href', type: 'string'}
]
});
Store:
Ext.require('MyLodge.model.Member');
Ext.define('MyLodge.store.Members', {
autoLoad: true,
autoSync: true,
model: 'MyLodge.model.Member',
proxy: {
type: 'rest',
url: 'http://localhost:8888/rest/memberapi/members' ,
reader: {
type: 'json',
root: 'data'
},
writer: {
type: 'json'
}
},
listeners: {
write: function(store, operation){
var record = operation.getRecords()[0],
name = Ext.String.capitalize(operation.action),
verb;
if (name == 'Destroy' ) {
record = operation.records[0];
verb = 'Destroyed';
} else {
verb = name + 'd';
}
Ext.example.msg(name, Ext.String.format( "{0} member: {1}", verb, record.getId()));
}
}
});
View:
Ext.define('MyLodge.view.content.MemberGrid', {
extend: 'Ext.grid.Panel',
alias: 'widget.membergrid',
initComponent: function(){
var store = Ext.create('MyLodge.store.Members' );
Ext.apply( this, {
height: this.height,
store: store,
stripeRows: true,
columnLines: true,
columns: [{
id : 'name',
text : 'Name',
flex: 1,
sortable : true,
dataIndex: 'name'
},{
text : 'E-Mail',
width : 150,
sortable : true,
dataIndex: 'email'
},{
text : 'Href',
width : 200,
sortable : true,
dataIndex: 'href'
}],
dockedItems: [{
xtype: 'toolbar',
items: [{
text: 'Add',
iconCls: 'icon-add',
handler: function(){
// empty record
store.insert(0, new MyLodge.model.Member());
rowEditing.startEdit(0, 0);
}
}, '-', {
itemId: 'delete',
text: 'Delete',
iconCls: 'icon-delete',
disabled: true,
handler: function(){
var selection = grid.getView().getSelectionModel().getSelection()[0];
if (selection) {
store.remove(selection);
}
}
}]
}]
});
this.callParent(arguments);
}
});
But I am not sure where to put the code to control the grid row selection and enable the Delete button:
grid.getSelectionModel().on('selectionchange', function(selModel, selections){
grid.down('#delete').setDisabled(selections.length === 0);
});
Also when I press the Add button I get the following error:
Uncaught TypeError: Object [object Object] has no method 'insert'.
Any help would be appreciated.
You are having scoping issues. Basically the variable store is defined only in the initComponent function and therefore of local function scope.
Your handler function has it's own scope. It is firing in the scope of the toolbar button. So if you say this in the handler it would refer to the button. Hence you can say this.up('panel').store - and that gives you the correct reference to the store backing your grid panel.
Another advice is not to implement everything at once. Write a little bit to see if it works and then add to it little by little.
RE: the docs examples, I agree that it's frustrating, but there's not many options. Having a fully-MVC-style implementation of each example would not only be onerous to produce, but would also probably make point of the example get lost in the structure.
RE: your question about the where to "put" the code to control the grid, I would recommend setting up a controller with listeners for the events on the grid in the control() section. This will let you decouple the handling of the events that are fired by your grid from the view itself.

Sencha touch 2 filterby() not updating records

I have a nested list on one of the pages of a Tabbed Panel app that is pulling data from "offices.json"
I should like to be able to filter this list when a user clicks on a toolbar button. However my filterBy() function doesn't update the store and the list of offices I can see, even though I can see in the console it is iterating the records and finding a match. What am I doing wrong?
(And yes I have tried doing s.load() both before and after the filterBy to no avail!)
toolbar:{
items:[{
text: 'Near you',
id: 'btnNearYou',
xtype: 'button',
handler: function() {
s = Ext.StoreMgr.get('offices');
s._proxy._url = 'officesFLAT.json';
console.log("trying to filter");
s.filterBy(function(record) {
var search = new RegExp("Altrincham", 'i');
if(record.get('text').match(search)){
console.log("did Match");
return true;
}else {
console.log("didnt Match");
return false;
}
});
s.load();
}
}]
For the record I'm defining my store like so:
store: {
type: 'tree',
model: 'ListItem',
id: 'offices',
defaultRootProperty: 'items',
proxy: {
type: 'ajax',
root: {},
url: 'offices.json',
reader: {
type: 'json',
rootProperty: 'items'
}
}
}
No need to recreate the regex each time, cache it outside.
You can simplify the code a lot (see below).
Why are you calling load directly after? That's going to send it to the server and it will just retrieve the same dataset.
toolbar: {
items: [{
text: 'Near you',
id: 'btnNearYou',
xtype: 'button',
handler: function() {
s = Ext.StoreMgr.get('offices');
s._proxy._url = 'officesFLAT.json';
var search = /Altrincham/i;
s.filterBy(function(record) {
return !!record.get('text').match(search);
});
}
}]
}

Simple login form with SenchaTouch

Just diving into SenchaTouch which seems very promising.
I'm building my first application, a simple login form check source http://pastebin.com/8Zddr9cj
I'm looking for a way to do the following things :
Display 'nice' error message when the login/password is wrong. Can be in red to replace the 'Please enter your credentials); i don't know how to access this property.
If login success, close the form and load the application (probably another js file).
Quite simple, but i'm a newbie to this,
1) Fieldset has a method called setInstructions which you can call to update the instructions. So, you could specify an id configuration in your field set, then use that later on when you want to update the instructions.
...
items: [
{
xtype: 'fieldset',
id: 'fieldset',
title: 'Login',
instructions: 'Please enter your credentials',
defaults: {
required: true,
labelAlign: 'left',
labelWidth: '40%'
},
items: [
{
xtype: 'emailfield',
name : 'email',
label: 'Email',
placeHolder: 'your#email.com',
useClearIcon: true
}, {
xtype: 'passwordfield',
name : 'password',
label: 'Password',
useClearIcon: false
}]
}
],
...
//wherever you want to update the instructions
var fieldset = Ext.getCmp('fieldset');
fieldset.setInstructions('My new instructions!');
2) Here is a simple demo of this:
//create a panel, which is full screen, and will contain your form, and another item
//which you want to show at some point
var wrapper = new Ext.Panel({
fullscreen: true,
layout: 'card',
//my two items
items: [
form,
{
xtype: 'panel',
html: 'my second panel, which is not visible on render.'
}
]
});
//change the active card/item, when you need to
wrapper.setActiveItem(1); //starts at 0
Make sure you remove fullscreen from your form, as it is no longer fullscreen (this wrapper panel is).