Ext js 7 modern, form.submit vs ajax.request - javascript

I have a Ext.form.Panel with multiple textareafield and fileinput like this
// https://requestbin.com/r/en0ej96odon2sm/1n6r1tb49KK6eObGMPHlYa1hh4C
Ext.create({
xtype: 'formpanel',
renderTo: document.body,
buttons: {
submit: 'onSubmit',
},
controller: {
onSubmit: function () {
var form = this.getView();
form.submit({
method: 'POST',
url: 'https://en0ej96odon2sm.x.pipedream.net/test1',
success: function () {}
});
},
onSubmitTest: function () {
var form = this.getView();
Ext.Ajax.request({
url: 'https://en0ej96odon2sm.x.pipedream.net/test2',
method: 'POST',
params: {
data: form.getValues(),
},
success: function () {}
});
},
},
items: [{
xtype: 'textareafield',
name: 'testfield',
label: 'testfield',
value: 'test\nasd',
}, {
xtype: 'filefield',
label: 'Upload Test',
name: 'basedata-test',
}, {
xtype: 'button',
text: 'Ajax.request(), linebreaks but no files',
handler: 'onSubmitTest',
}]
});
Post Results:
https://requestbin.com/r/en0ej96odon2sm/1n6mtu8QtyreaisCAmV3csO724Q
Fiddle:
https://fiddle.sencha.com/#view/editor&fiddle/3b9j
So, cause i need fileinput/multipart, I have to use form.submit({}).
But when I do so, I don't get the linebreaks on Server side in my $_POST Var.
When I do a ajax.request({}) everything looks good, but $_FILES are missing, so this is not really an option. (but this is documented).
I also tried adding jsonSubmit to the form (then I get no $_POST at all).
When I add enableSubmissionForm: false I get the newline, but after submit the form disappears (and I don't know why).
Is there a solution for this or am I doing something wrong?

You can use the following override. Hope it will not make the framework unstable ;)
// https://requestbin.com/r/en0ej96odon2sm/1n6r1tb49KK6eObGMPHlYa1hh4C
// Override
Ext.define('overrides.form.Panel', {
override: 'Ext.form.Panel',
privates: {
createSubmissionForm: function (form, values) {
var fields = this.getFields(),
name, input, field, fileTrigger, inputDom;
if (form.nodeType === 1) {
form = form.cloneNode(false);
for (name in values) {
input = document.createElement('textarea');
input.setAttribute('type', 'string');
input.setAttribute('name', name);
input.innerHTML = values[name];
form.appendChild(input);
}
}
for (name in fields) {
if (fields.hasOwnProperty(name)) {
field = fields[name];
if (field.isFile) {
// The <input type="file"> of a FileField is its "file" trigger button.
fileTrigger = field.getTriggers().file;
inputDom = fileTrigger && fileTrigger.getComponent().buttonElement.dom;
if (inputDom) {
if (!form.$fileswap) {
form.$fileswap = [];
}
input = inputDom.cloneNode(true);
inputDom.parentNode.insertBefore(input, inputDom.nextSibling);
form.appendChild(inputDom);
form.$fileswap.push({
original: inputDom,
placeholder: input
});
}
} else if (field.isPassword) {
if (field.getInputType() !== 'password') {
field.setRevealed(false);
}
}
}
}
return form;
}
}
});
Ext.create({
xtype: 'formpanel',
renderTo: document.body,
buttons: {
submit: 'onSubmit',
},
controller: {
onSubmit: function () {
var form = this.getView();
form.submit({
method: 'POST',
url: 'https://en0ej96odon2sm.x.pipedream.net/test1',
success: function () {}
});
},
onSubmitTest: function () {
var form = this.getView();
Ext.Ajax.request({
url: 'https://en0ej96odon2sm.x.pipedream.net/test2',
method: 'POST',
params: {
data: form.getValues(),
},
success: function () {}
});
},
},
items: [{
xtype: 'textareafield',
name: 'testfield',
label: 'testfield',
value: 'test\nasd',
}, {
xtype: 'filefield',
label: 'Upload Test',
name: 'basedata-test',
}, {
xtype: 'button',
text: 'Ajax.request(), linebreaks but no files',
handler: 'onSubmitTest',
}]
});

Not ideal, but you also can do this:
form.submit({
method: 'POST',
//just like the ajax
params: {
data: form.getValues(),
},
url: 'https://en0ej96odon2sm.x.pipedream.net/test1',
success: function () {}
});

Here is a simple workaround for using Ajax.request instead of form.submit
I needed that because I have to set an Authorization header, which can't be done with IFRAME used by the framework
So preventing Ext.data.request.Ajax from setting Content-Type header seems to do the job.
multipart/form-data will be automatically set.
Warning : neither options.headers nor defaultHeaders should already have the 'Content-Type' header
Ext.define('Override.data.request.Ajax', {
override: 'Ext.data.request.Ajax',
setupHeaders: function(xhr, options, data, params) {
if (data instanceof FormData) {
if (Ext.apply({}, options.headers || {}, this.defaultHeaders).hasOwnProperty('Content-Type')) {
console.warn('The Content-Type header must not be set before request if you need to use FormData with this override');
}
/* prevent Ext.data.request.Ajax from setting Content-Type header */
return this.callParent([xhr, options, null, null]);
} else {
return this.callParent(arguments);
}
}
});
And call Ajax.request with a FormData as rawData
var formData = new FormData();
var files = myView.down('filefield').getFiles();
if (files.length > 0) {
formData.append('file', files[0], files[0].name);
}
Ext.Ajax.request({
url: 'your_url',
rawData: formData,
success: function(response) {
// handle success
},
failure: function(response) {
// handle failure
}
});

Related

Unable to preselect value on select2

I'm using this library
https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.full.js">
I know there are a lot of examples out there and I've tried them all most recent:
var $client_id = $("#client_id").select2({
dropdownParent: $('#categoryForm'),
ajax: {
quietMillis: 300,
url: apiPath,
xhrFields: {
withCredentials: true
},
crossDomain: true,
type: "GET",
data: function (params) {
var queryParameters = {
search: params.term
}
return queryParameters;
},
processResults: function (data) {
return {
results: $.map(data.data, function (item) {
return {
text: item.client_name,
id: item.client_id
}
})
};
}
}
});
$client_id.val(6).trigger('change');
As you can see at the bottom I'm trying to select the value using the (valid) ID. I have been successfull using this method:
var option = new Option(data.customer_name, data.customer_id, true, true);
customerSelect.append(option).trigger('change');
But I'd rather just use the ID if it's possible

Autocomplete - change lookup/serviceurl based on dropdown selection

I have a dropdown with multiple options to select. When I select value1 (company), autocomplete should use the service call. When I select value2, lookup should be used.
How can I implement this?
$('#qckSearchKeyword').autocomplete({
serviceUrl: function() {
var option = $('#qck-unspsc').val();
if (option == "country") {
// when country selected through drop down i should use lookup rather then service call
serviceloc = "getCountries";
localStorage.option = "country";
}
if (option == "industry") {
serviceloc = "getSicCode";
localStorage.option = "sicCode";
}
return serviceloc;
},
onSelect: function(suggestion) {
localStorage.tmpSelectedTxt = $.trim($('#qckSearchKeyword').val());
$('#selectFromSuggestions').val("true");
$('#qckSearchKeyword').focus();
},
paramName: "searchTerm",
delimiter: ",",
minChars: 3,
transformResult: function(response) {
// alert(response);
return {
suggestions: $.map($.parseJSON(response), function(item) {
return {
value: item.suggesCode,
data: item.suggesString
};
})
};
}
});
Split up the options for the different autocomplete calls.
Use a data-type on the options you select.
Switch the data-type and extend the proper options
Init autocomplete with proper options
I simply copy/pasted some configuration I've done in the past for this functionality:
...
ajaxOptionsFlight: {
url: '/api/autocomplete/airport/',
type: 'get',
dataType: 'xml'
},
ajaxOptionsHotel: {
url: '/api/locations/hotel/',
type: 'get',
dataType: 'xml'
},
ajaxOptionsCitytrip: {
url: 'http://budapest.onlinetravel.ch/destfinder',
dataType: 'jsonp',
data: {
vendors: 'merger',
client: 'conbe',
filter: 'IATA',
format: 'json',
language: 'en'
}
},
ajaxOptionsCar: {
url: '/api/locations/car/',
dataType: 'json'
},
ajaxOptionsSubstitute: {
url: 'http://gd.geobytes.com/AutoCompleteCity',
dataType: 'jsonp'
},
autocompleteOptions: {
autoFocus: true,
minLength: 1
},
....
After that I make sure I can switch on data-type and hook it on the source parameter of the autocomplete options:
autocompleteOptions = $.extend({}, autocompleteOptions, {
source: type === 'citytrip' ? function (request, response) {
ajaxOptions = $.extend(true, {}, ajaxOptionsCitytrip, {
data: {
name: $.trim(request.term),
language: cookieLanguage
},
success: function (d) {
response($.map(d.Destinations, function (item) {
return {
label: item.name + ', ' + item.country,
value: item.name,
code: item.olt_id
};
}));
}
});
$.ajax(ajaxOptions);
} : type === 'flight' ? function (request, response) {
ajaxOptions = $.extend({}, ajaxOptionsFlight, {
url: ajaxOptionsFlight.url + $.trim(request.term),
success: function (d) {
response($.map($(d).find('airport'), function (item) {
return {
label: $(item).children("displayname").text(),
value: $(item).children("displayname").text(),
code: $(item).children("code").text()
};
}));
}
});
$.ajax(ajaxOptions);
} : type === 'hotel' ? function (request, response) {
// and so on ...
}
});
Not the most elegant way of writing, I admit. But it's basically a simple mapping between data-type and configuration options to provide for autocomplete.
In the end I only call:
input.autocomplete(autocompleteOptions);
And we're done. Hope that makes sense.

How to get value from textfield to variables

Im using Mvc in C#.net and extjs. My question is
how to get value from textfield then set it to a variable and send email to multiple recipient.
This is my code for sending an email, and i want to get the values from the Extjs textfield id and set the id to a variable in sending. Then i want to send email to multiple recipient.
{
xtype: 'toolbar',
flex: 1,
dock: 'bottom',
ui: 'footer',
layout: {
pack: 'end',
type: 'hbox'
},
items: [{
xtype: 'button',
text: 'Send Email',
itemId: 'sen',
//iconCls: 'cancel'
handler: function() {
var rec = Ext.getCmp("activityGrid").getSelectionModel().selected()[0]
Ext.Ajax.request({
url: '/tblt_UAT_hr/generatePreview',
method: 'POST',
params: {
// id: Ext.get("Uath_Id").getValue(),
desc: rec.get("pc_desc"),
uat_date: rec.get("UAT_date"),
pcno: rec.get("pc_no"),
name: rec.get("name"),
stkid: rec.get("Stkhid")
},
success: function(resp) {
var result = Ext.decode(resp.responseText);
if (result.success) {
Ext.Ajax.request({
url: '/tblt_UAT_hr/SendEmailsTo',
method: 'POST',
params: {
from: null,
to: Ext.getCmp('to').getValue(),
subject: Ext.getCmp('subject').getValue(),
body: Ext.getCmp('bod').getValue(),
file: result.file
},
success: function(resp) {},
failure: function() {}
});
} else
mask.hide();
},
failure: function() {
mask.hide();
}
});
}
}, {
xtype: 'button',
text: 'Cancel',
itemId: 'can',
//iconCls: 'save'
}]
}]
public JsonResult SendEmailsTo(string from, string to, string subject, string body, string file) {
if (file != "" && file != null) {
MailMessage mail = new MailMessage();
SmtpClient smtpServer = new SmtpClient("smtp.gmail.com");
smtpServer.Credentials = new System.Net.NetworkCredential("ga.ojt.sunga#gmail.com", "1993doris");
smtpServer.Port = 587; // Gmail works on this port
string newfile = Server.MapPath("~/Content/pdf") + "\\" + file;
Attachment attachment = new Attachment(newfile);
mail.From = new MailAddress("ga.ojt.sunga#gmail.com");
//mail.To.Add(emailAdd);
foreach(var address in to.Split(new [] {
";"
}, StringSplitOptions.RemoveEmptyEntries)) {
mail.To.Add(address);
}
mail.Subject = subject;
mail.Body = body;
mail.Attachments.Add(attachment);
smtpServer.EnableSsl = true;
smtpServer.Send(e);
// return Content("email sent", "text/plain");
}
return Json(new {
success = true, msg = "success"
}, JsonRequestBehavior.AllowGet);
}
Find the text field, with ComponentQuery or otherwise, call getValue on it and add it to params of a request call. Pseudo code:
var field = Ext.ComponentQuery.query('#fieldItemId')[0];
params:{
yourField:field.getValue();
}

How can I assign an HTML5 data value to an element?

I have the following code:
$.modal({
title: title,
closeButton: true,
content: content,
complete: function () {
applyTemplateSetup();
$('#main-form').updateTabs();
$('#main-form').data('action',action);
// updated to line below but still does not work
$('#main-form').data('action','Edit');
},
width: 900,
resizeOnLoad: true,
buttons: {
'Submit': function (win) {
formSubmitHandler($('#main-form'));
},
}
Once my data is loaded I am trying to set the data attribute action. I then have more code that reads it in the submit handler:
var formSubmitHandler = function (form) {
//e.preventDefault();
var $form = form;
var val = $form.valid();
if (!$form.valid || $form.valid()) {
var submitBt = $(this).find('button[type=submit]');
submitBt.disableBt();
var sendTimer = new Date().getTime();
$.ajax({
url: $form.attr('action'),
dataType: 'json',
type: 'POST',
data: $form.serializeArray(),
success: function (json, textStatus, XMLHttpRequest) {
json = json || {};
if (json.success) {
if ($form.data('action') == "Edit") {
$('#modal').removeBlockMessages()
submitBt.enableBt();
} else {
However it seems the value is not being set correctly as when I step through the code this is not getting a true value: $form.data('action') == "Edit". Am I doing something wrong?
This might be the issue.
First you do - $('#main-form').data('action',action);
I'm not entirely sure what the actionvariable holds, but from this line of your code - url: $form.attr('action') I'm going to assume you're giving the form action value. Why you do that is your concern, but I do believe it does not == "Edit".
What value do you get in your $form.data('action') ?

form.submit() to a specific DIV

I want to submit a form using Javascript and jQuery to specific div but I can't work out how to do it.
This code below works, submitting the form to the header of the current page.
var form,
chart = this,
svg = chart.getSVG(chartOptions);
// merge the options
options = merge(chart.options.exporting, options);
// create the form
form = createElement('form', {
method: 'post',
action: options.url
}, {
display: NONE
}, doc.body);
// add the values
each(['filename', 'type', 'width', 'svg'], function(name) {
createElement('input', {
type: HIDDEN,
name: name,
value: {
filename: options.filename || 'chart',
type: options.type,
width: options.width,
svg: svg
}[name]
}, null, form);
});
// submit
form.submit();
// clean up
discardElement(form);
I have tried various options but nothing has worked. In simple terms I want to do this:
$('#myDiv').form.submit();
Or in other words, send the submit command to the div named myDiv.
Does anyone know how I would do this? Thanks.
You should be able to use the code given here:
Post form in JQuery and populate DIV - broken in IE
$.ajax({
url: options.url,
type: 'POST',
cache: false,
data: {
filename: options.filename || 'chart',
type: options.type,
width: options.width,
svg: svg
},
dataType: 'text',
complete: function(xhr, textStatus) {
alert('completed');
},
success: function(data) {
$("#myDiv").html(data);
},
error: function(xhr, textStatus, errorThrown) {
alert('woops');
}
});
$('#myDiv').click (function () {
$("form").submit();
});

Categories

Resources