posting form to iframe with extjs without rendering to bidy - extjs

I am trying to post a form to an iframe. my issue is that my form gets posted just fine when I render the iframe to body. But the issue with this is that the container displays at the bottom of the page instead of the place where I want it to show. If I don't use the renderTo property, my form never gets posted to iframe at all. It almost seems like that in the case when I do not use renderTo property, i think my form does not even see the iframe.
here is my code thats working for the form post but the container falls all the way to the bottom of the page
var myContainer = Ext.create('Ext.form.FieldSet', {
title: "my frame container",
labelWidth: 1,
bodyStyle: "padding-right:15px;padding-left:25px;",
renderTo: Ext.getBody(),
items: [
{
xtype: 'box',
autoEl: {
tag: 'iframe',
name: 'myIframe',
id: 'myIframe'
}
}
]
});
$('myform').submit();
This gets the form submitted but the panel drops down to the bottom of page. How can I keep its location and also be able to post to it.
Again if I take this part out renderTo: Ext.getBody() then the form never gets posted to iframe.
I wonder if there is a way to render to a specific div may be? Not sure if that would work as well.
EDITED
I tried doing this
renderTo: 'x-panel'
ext-all.js Uncaught TypeError: Cannot read property 'dom' of null
** Complete Code with form Submission **
var f = document.createElement("form");
f.setAttribute('method',"post");
f.setAttribute('name',"checkout-form");
f.setAttribute('id',"checkout-form");
f.setAttribute('target',"myIframe");
f.setAttribute('action',"http://example.com");
var formFields = [
'field1',
'field2',
field3'
];
for (var i = 0; i < formFields.length; i++){
var formFieldName = 'formFieldName'+i;
formFieldName = document.createElement("input");
formFieldName.type = "text";
formFieldName.name = formFields[i];
f.appendChild(formFieldName);
}
var myContainer = Ext.create('Ext.form.FieldSet', {
title: "my title",
labelWidth: 1,
bodyStyle: "padding-right:15px;padding-left:25px;",
//renderTo: Ext.getBody(),
renderTo: Ext.getElementById("myId"),
items: [
{
xtype: 'box',
autoEl: {
tag: 'iframe',
name: 'myIframe',
id: 'myIframe',
},
listeners: {
load: {
element: 'el',
fn: function () {
console.log("iframe loaded");
$('iframe#component-9808').css('border','0');
}
}
}
}
]
});
$("body").append(f);
$('#checkout-form').submit();

Maybe you can try to send your form data like this:
Ext.create(Ext.form.Panel).submit({
clientValidation: false,
method: 'GET',
params: {
// Your params like:
id: myId
},
standardSubmit: true,
target: '_blank',
url: 'your/url'
});

var formFields = [
'field1',
'field2',
field3'
];
You have one ' missing there also... Wacthout!

Related

extjs store.load after form.submit

I'm trying to reload an Extjs-store, after user has download a PDF.
The process is the following:
User double clicks a cell in GridPanel
Form is created, submitted, and a procedure in the backend creates an PDF and makes some changes on data of GridPanel store
PDF will be downloaded by user
But how to reload the store with the new data in it?
There is no afterRender on form-submit.
I think this should be an easy problem, but I do not have any ideas how to solve it.
This is a snipped I found in my code base (inside a controller):
var form = button.up().up().down('form').getForm();
form.submit({ success : this.onFileUpload, failure: this.onFileUpload, scope: this});
...
onFileUpload: function (form, action){
var data = action.result.data;
...
if (action.result.success){
...
//**your store reload could be here!**
...
} else {
...
}
}
My form response is not responding with a file (just some standard html return), but I guess it should work.
here is a bit of my code:
function makeprintForm(array, setStatusX, grid) {
var filename = 'asd.pdf';
var url_pdf = 'someURL?FileName=' + filename;
var printForm = Ext.create('Ext.form.Panel', ({
url: currentContextPath + encodeURIComponent('http://' + host + ':' + port + url_pdf),
hidden: true,
id: 'printForm',
name: 'printForm',
method: 'post',
standardSubmit: true,
target: '_blank',
items: [{
xtype: 'textfield',
fieldLabel: 'print_id',
name: 'print_id',
value: array
},
{
xtype: 'textfield',
fieldLabel: 'username',
name: 'username',
value: username
},
{
xtype: 'textfield',
fieldLabel: 'language_field',
name: 'language',
value: language
}
]
}));
Ext.getCmp('printForm').getForm().submit({ success : this.reload_grid_after_submit(), scope: document.getElementById(nameSpace + 'formIS')});
}
function reload_grid_after_submit(){
console.log('reload_grid_after_submit');
Ext.getCmp('grid').getStore().proxy.setExtraParam('status', 'NEW');
Ext.getCmp('grid').getStore().load();
}
You can use a form in an alert box. I used a window here. Then onsubmit of the form you can use findRecord to find a record from the store and edit it. For better explanation please find the fiddle here. P.S sorry for the delay I was on a vacation. Please mark it as an answer if it's correct so it helps other people in the future. Or please comment if there is something which needs to be changed. Thanks
Ext.getCmp('myGrid').addListener('rowdblclick', function (a, b, c, d) {
win = new Ext.Window({
width: 300,
height: 150,
draggable: false,
border: false,
modal: true,
resizable: false,
items: [{
xtype: 'textfield',
fieldLabel: 'What is your new name',
id: 'newNameField'
}, {
xtype: 'button',
name: 'sampleButton',
text: 'Change My Name!',
style: 'margin:15px',
width: 150,
handler: function () {
name = Ext.getCmp('myGrid').getStore().getAt(d).data['name'];
console.log(name);
var newName = Ext.getCmp("newNameField").value;
console.log("replacing " + name + " with " + newName + " in the store");
var entry = userStore.findRecord('name', name);
entry.set('name', newName);
win.hide();
}
}]
})
win.show();
})

Trying to create a fieldset for each item in a store

I'm very new to ExtJS and getting quite lost. I have created a data store -
var sections = Ext.create('Ext.data.Store', {
data: [
{"section" : "One"},
{"section" : "Two"},
{"section" : "Three"}
]
});
What I would like to do now is create a panel for each section, using the section name (one, two three) as the title.
I have tried a few ways, all of which are really unsuccessful. How do I go about solving this problem?
EDIT - Example of something I tried
var sectionStore = Ext.getStore(sections);
var allRecords = sectionStore || sectionStore.data("section");
allRecords.each(function(record) {
Ext.define('Ext.panel.Panel', {
xtype: 'panel',
title: record,
text: record
})
console.log(record)
});
Ext.define defines classes, but you want to create new instances of the panel class and add them to the component hierarchy.
So that's what you have to do (you can add them to any existing and already rendered container component):
var parentContainer = ...
var sectionStore = Ext.getStore(sections);
var allRecords = sectionStore || sectionStore.data("section");
allRecords.each(function(record) {
parentContainer.add({
xtype: 'panel',
title: record,
text: record
});
});
As you are using Ext.define('Ext.panel.Panel', You just only define a panel. Instead of define you need to use Ext.create().
FIDDLE
CODE SNIPPET
Ext.application({
name: 'Fiddle',
launch: function () {
var sections = Ext.create('Ext.data.Store', {
data: [{
"section": "One"
}, {
"section": "Two"
}, {
"section": "Three"
}]
}),
fieldSetItems = [];
sections.each(rec => {
fieldSetItems.push({
xtype: 'fieldset',
title: rec.get('section')
});
});
Ext.create({
xtype: 'panel',
title: 'Create Items by store',
items: fieldSetItems,
renderTo: Ext.getBody()
});
}
});

ExtJS 6 - How to upload a file without using form?

Ext JS provides fileuploadfield which is bundled with a button to browse local files. I just need to upload a file using as soon as it is selected from local instead of using a submit button in order to trigger the post process. Could not find an event which is fired after the file is selected.
p.s. Actually, the version I use is Ext JS 6 but I think the solutions based on previous versions do the work as well.
Form is not required. You can use AJAX and FormData.
var file = s.fileInputEl.dom.files[0],
data = new FormData();
data.append('file', file);
Ext.Ajax.request({
url: '/upload/files',
rawData: data,
headers: {'Content-Type':null}, //to use content type of FormData
success: function(response){ }
});
Online demo here
You will need to use a form if you want to submit the file. Even if you want the button to be in a toolbar, you can enclose it in a form and it will still look like a normal toolbar button (you will need to specify the proper ui config for this).
Example:
dockedItems: [{
dock: 'top',
xtype: 'toolbar',
items: [{
xtype: 'form',
padding: '10 0 0',
url: 'submit/image',
items: {
xtype: 'filefield',
buttonOnly: true,
width: 100,
buttonConfig: {
text: 'Add logo',
width: '100%',
ui: 'default-toolbar-small'
},
listeners: {
change: function (filefield) {
filefield.up('form').submit();
}
}
}
}, {
text: 'Remove logo'
}, '-', {
text: 'Discard changes'
}]
}]
Working fiddle example: https://fiddle.sencha.com/#view/editor&fiddle/1pdk
While I agree with scebotari's answer that in your case embedding a form in the toolbar is probably the easiest solution, for the sake of answering the original question:
If you really cannot or do not want to use a form and you're not limited regarding browser support, have a look at the FileReader.
The idea is to read the file contents on the client side (JavaScript) and then send the data using a regular AJAX request.
Your code could look like that:
function (fileField) {
var file = fileField.fileInputEl.dom.files[0],
reader;
if (file === undefined || !(file instanceof File)) {
return;
}
reader = new FileReader();
reader.onloadend = function (event) {
var binaryString = '',
bytes = new Uint8Array(event.target.result),
length = bytes.byteLength,
i,
base64String;
// convert to binary string
for (i = 0; i < length; i++) {
binaryString += String.fromCharCode(bytes[i]);
}
// convert to base64
base64String = btoa(binaryString);
Ext.Ajax.request({
url: 'save-file.php',
method: 'POST',
params: {
data: base64String
}
});
};
reader.readAsArrayBuffer(file);
}
You are looking for the event change on the fileuploadfield.
The code could look like this:
Ext.create('Ext.form.Panel', {
renderTo: Ext.getBody(),
title: 'Upload Panel',
items: [{
xtype: 'filefield',
name: 'photo',
fieldLabel: 'Photo',
labelWidth: 50,
msgTarget: 'side',
allowBlank: false,
anchor: '100%',
buttonText: 'Select Photo...',
listeners: {
change: function (me, value, eOpts) {
console.log('trigger upload of file:', value);
}
}
}],
});
Fiddle https://fiddle.sencha.com/#view/editor&fiddle/1pd2

Resetting event handlers in ExtJS

I have a page where there are multiple records. Each record has a button to open a dialog box to create a name. The name then creates a related record in the database and updates the source record.
There is a single dialog box instantiated and I want to show the dialog box, get the result and return it to the correct record.
The code below works once but doesn't work the second time. I can see the the Create button gets clicked but the event doesn't got caught.
Many thanks for your help.
TrailNamePresenter.prototype.onCreateTrailClick = function (trailSegment, combo, personalRouteId) {
if (!this.createTrailWindow) {
this.createTrailWindowPanel = new CreateTrailFormPanel();
this.createTrailWindow = new Ext.Window({
title: 'Create Trail',
closable: true,
closeAction: 'hide',
plain: true,
items: [this.createTrailWindowPanel],
id: 'createtrailwindow'
});
}
this.createTrailWindowPanel.on('createTrail', this.getCreateTrailHandler(personalRouteId, trailSegment, combo), null, {single:true});
this.createTrailWindow.show();
};
TrailNamePresenter.prototype.getCreateTrailHandler = function(personalRouteId, trailSegment, currentTrailCombo) {
var thisPersonalRouteId = personalRouteId;
var thisPresenter = this;
var thisCurrentTrailCombo = currentTrailCombo;
var thisTrailSegment = trailSegment;
return function(newTrailName) {
thisPresenter.mapEditorService.createPersonalTrail(newTrailName, thisPersonalRouteId, thisPresenter.getCreateTrailServiceHandler(thisCurrentTrailCombo, thisTrailSegment));
};
};
CreateTrailFormPanel = Ext.extend(Ext.form.FormPanel, {
initComponent: function() {
Ext.apply(this, {
id: 'createtrailpanel',
width: 500,
frame: true,
bodyStyle: 'padding: 10px 10px 0 10px;',
labelWidth: 50,
defaults: {
anchor: '95%',
msgTarget: 'side'
},
items: [
{
id: 'crt_trailnamefield',
xtype: 'textfield',
fieldLabel: 'Trail Name'
}
],
buttons: [{
text: 'Create',
handler: this.getCreateClickHandler()
},{
text: 'Cancel',
handler: function(b, e){
Ext.getCmp('createtrailwindow').hide();
}
}]
});
this.addEvents('createTrail');
CreateTrailFormPanel.superclass.initComponent.apply(this, new Array());
}
});
CreateTrailFormPanel.prototype.getCreateClickHandler = function() {
var thisPanel = this;
return function() {
var trailNameField = Ext.getCmp('crt_trailnamefield');
alert('click');
thisPanel.fireEvent('createTrail', trailNameField.getValue());
};
};
In ExtJS, when you have components that will belong to a parent. I would suggest using itemID, otherwise the ability of reuse of the component across your web application is reduced because id acts similarly to a singleton. Also on the action, you have {single:true} which will remove the listener after the first trigger. IF you remove that, it may solve your issue

Ext JS Tab Panel - Dynamic Tabs - Tab Exists Not Working

Would appreciate if somebody could help me on this.
I have a treepanel whose nodes when clicked load a tab into a tabpanel.
The tabs are loading alright, but my problem is duplication. I need to check if a tab exists before adding it to the tab panel. I cant seem to have this resolved and it is eating my brains. This is pretty simple and I have checked stackoverflow and the EXT JS Forums for solutions but they dont seem to work for me or I'm being blind.
This is my code for the tree:
var opstree = new Ext.tree.TreePanel({
renderTo: 'opstree',
border: false,
width: 250,
height: 'auto',
useArrows: false,
animate: true,
autoScroll: true,
dataUrl: 'libs/tree-data.json',
root: {
nodeType: 'async',
text: 'Tool Actions'
},
listeners: {
render: function() {
this.getRootNode().expand();
}
}
});
opstree.on('click', function(n) {
var sn = this.selModel.selNode || {}; // selNode is null on initial selection
renderPage(n.id);
});
function renderPage(tabId) {
var TabPanel = Ext.getCmp('content-tab-panel');
var tab = TabPanel.getItem(tabId);
//Ext.MessageBox.alert('TabGet',tab);
if (tab) {
TabPanel.setActiveTab(tabId);
} else {
TabPanel.add({
title: tabId,
html: 'Tab Body ' + (tabId) + '<br/><br/>',
closable: true
}).show();
TabPanel.doLayout();
}
}
And this is the code for the tabpanel:
new Ext.TabPanel({
id: 'content-tab-panel',
region: 'center',
deferredRender: false,
enableTabScroll: true,
activeTab: 0,
items: [{
contentEl: 'about',
title: 'About the Billing Ops Application',
closable: true,
autoScroll: true,
margins: '0 0 0 0'
}, {
contentEl: 'welcomescreen',
title: 'PBRT Application Home',
closable: false,
autoScroll: true,
margins: '0 0 0 0'
}]
});
Can somebody please help?
The key to doing this is to build a consistent naming convention for your tabs, so you can reliably know if that tab has been added yet. It looks like you've chosen to use the node's id - which is fine. When you call TabPanel.add, send the node's id as the new tab's id. Then you can test to see if it exists with TabPanel.findById.
Note: some of your variable names are pretty confusing. TabPanel is a poor choice for a variable name, keep them beginning with lower case and never name them after the framework classes. Try tabs or tp. Also, the naming convention will be clearer if you prefix the node id with a string like tab-. Adding a new tab could also be encapsulated into a custom method on your tab panel, if you extend it.
There has been some modifications on the Extjs API .findById() doesn't work, to implement this in ExtJs 4.0 try this
function AddTabs(tabTitle,yourTabId){
var YourTabPanel = Ext.getCmp('YourTabPanelId');
var TabToCheck = YourTabPanel.getChildByElement(yourTabId);
if(TabToCheck){
YourTabPanel.setActiveTab(yourTabId);
} else {
YourTabPanel .add({
title:tabTitle,
id:nId,
closable:true,
autoScroll:true,
layout: 'fit',
}).show();
}
YourTabPanel.doLayout();
}
function addNewTab(nName,nId){
//nName is Node Name and nId is node Id
//Ext.Msg.alert('message',nId);
var tp = Ext.getCmp('content-tab-panel');//Tab Panel Id
var checkTab=tp.findById(nId);
if(checkTab){
tp.setActiveTab(nId);
} else {
tp.add({
title:nName,
id:nId,
closable:true,
autoScroll:true
}).show();
}
}
You should replace the function renderPage(tabId) with the following:
function renderPage(tabId) {
var TabPanel = Ext.getCmp('content-tab-panel');
var tab = TabPanel.getItem(tabId);
//Ext.MessageBox.alert('TabGet',tab);
if(tab){
TabPanel.setActiveTab(tabId);
}
else{
TabPanel.add({
title: tabId,
html: 'Tab Body ' + (tabId) + '
',
id: tabId,**// this line very important, without this its not working**
closable:true
}).show();
TabPanel.doLayout();
}
}
Untested, but I think this would work.
if (!Ext.getCmp('content-tab-panel')) {
Tabpanel.add({ config }).show();
Tabpanel.doLayout();
}

Resources