Within a SharePoint form overriden by CSR (Client Side Rendering).
I tried adding a new button which does pretty much the same as the Save button except that it redirects to another form with given parameters.
The thing is, the redirection does not work.
I tried redirecting by changing the "action" property of the form but it doesn't seem to be taken in count.
Here is the new button :
<input id="custom_addLine" type="button" name="custom_addLine" value="+" class="ms-ButtonHeightWidth">
Here is the function called by the button and the addLine method following :
$('#custom_addLine').click(function(event){
event.preventDefault();
addLine(getQueryStringParameter('ID'));
});
function addLine(id) {
if(!PreSaveItem()) {
return false;
}
var actionUrl = "/Lists/PurchaseRequestLine/NewForm.aspx?PurchaseRequestID="+ id;
var encodedActionUrl = encodeURIComponent(actionUrl);
var newFormAction = location.pathname + '?Source=' + encodedActionUrl;
$('#aspnetForm').attr('action',newFormAction);
if(SPClientForms.ClientFormManager.SubmitClientForm('WPQ1')){
return false;
}
WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions('custom_addLine', "", true, "", "", false, true));
}
getQueryStringParameter is a custom made function to retrieve parameters from URI (which works).
The tricky part is that I want to preserve the default action URI in case the original Save button is clicked on, which is why action parameter is modified on the fly.
You can change the Source attribute directly from the original action:
function addLine(id) {
if(!PreSaveItem()) {
return false;
}
var oldActionUrl = $('#aspnetForm').attr('action');
var oldSource = GetUrlKeyValue("Source", true, oldActionUrl);
var newSource = "/Lists/PurchaseRequestLine/NewForm.aspx?PurchaseRequestID="+ id;
var newActionUrl = oldActionUrl.replace(oldSource, encodeURIComponent(newSource));
WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions('custom_addLine', "", true, "", newActionUrl, false, true));
}
Please remove event.preventDefault(); from your code, it is responsible for redirection does not work
$('#custom_addLine').click(function(event){
addLine(getQueryStringParameter('ID'));
});
Related
I'm typing this question away from my computer so I don't have the exact code, but the question might be straightforward enough without it.
When I have a submit button directly within an Ajax form and I click the button directly to submit, everything works fine, and as expected. The Ajax.Form POSTs back to the controller which returns a partial view that is rendered inside the current View that I have.
But what I need is for a button to be clicked in the Ajax.Form, and for a JavaScript function to run. The JavaScript function will do some vaildation which decides whether to submit the Ajax.Form or not.
I have tried putting 2 buttons in the Ajax.Form, a hidden submit button and a regular button. I used the onclick event of the regular button to call my JavaScript function which then called the click method of the hidden submit button. (I have also tried just submitting the Ajax.Form directly with document.forms[formname].submit() )
This sort of works.. But not correctly for some reason. The Ajax.Form POSTs back to the controller but when a partial view is returned from the controller, the partial view is the only thing rendered, and it is rendered as basic html with no css/bootstrap.
What is the difference between actually clicking the submit button and doing so programmatically?
How can Achieve what I am trying to do?
Edit
#using (Ajax.BeginForm("GetInstructorInfo", "Incident", FormMethod.Post, new AjaxOptions { OnBegin = "lookupInstructor();", UpdateTargetId = "InstructorInfo" }, new { #class = "form-inline", role = "form", #id = "instructorInfoForm", #name = "instructorInfoForm" }))
{
//code in here
}
Edit 2 / 3:
<script>
function lookupInstructor()
{
if ($('input[name="Instructors['+userInputInstructor+'].Username'+'"]').length > 0) //Don't allow user to enter multiple instances of the same Instructor
{
document.getElementById("InstructorUsername").value = ''; //clear textbox value
return false;
}
var userInputInstructor = document.getElementById("InstructorUsername").value;
$.ajax({
url: '#Url.Content("~/Incident/LookUpUsername")',
data: { userInput: userInputInstructor },
success: function (result) {
if (result.indexOf("not found") != -1){ //if not found
$("#InstructorNotFoundDisplay").show();
document.getElementById("InstructorUsername").value = ''; //clear textbox value
$('#InstructorInfo').empty();
return false;
}
else {
$("#InstructorNotFoundDisplay").hide();
return true;
}
}
});
}
</script>
You can use the OnBegin() ajax option to call a function that runs before the form is submitted (and return false if you want to cancel the submit). For example
function Validate() {
var isValid = // some logic
if (isValid) {
return true;
} else {
return false;
}
}
and then in the Ajax.BeginForm() options
OnBegin = "return Validate();"
Edit
Based on the edits to the question and the comments, you wanting to call an ajax function in the OnBegin() option which wont work because ajax is asynchronous. Instead, use jQuery.ajax() to submit you form rather than the Ajax.BeginForm() method (and save yourself the extra overhead of including jquery.unobtrusive-ajax.js).
Change Ajax.BeginForm() to Html.BeginForm() and inside the form tags replace the submit button with <button type="button" id="save">Save</button>and handle its .click() event
var form = $('#instructorInfoForm');
var url = '#Url.Action("GetInstructorInfo", "Incident")';
var target = $('#InstructorInfo');
$('#save').click(function() {
if ($('input[name="Instructors['+userInputInstructor+'].Username'+'"]').length > 0) {
....
return; // exit the function
}
$.ajax({
....
success: function (result) {
if (result.indexOf("not found") != -1) {
....
}
else {
$("#InstructorNotFoundDisplay").hide();
// submit the form and update the DOM
$.post(url, form.serialize(), function(data) {
target.html(data);
});
}
}
});
});
I'm having some problems with the Dropzone.js. After I create a dropzone I want to change its values (for example the url) before sending the form via POST.
I already set the variable autoProcessQueue to false, so I can send the files when the form is sent.
Here is a test that I made but is not working...
var myDropzone = new Dropzone(me, {
url: uploadUrl
,maxFilesize: 10
,addRemoveLinks: true
,addDownloadLinks: true
,downloadFileUrl: downloadUrl
,autoProcessQueue: false
,init: function() {
var myDrop = this;
$("[id=btnSendMessage]").click(function(e){
// e.preventDefault();
url2 = '/file/upload/52175';
myDrop.url = url2;
myDrop.processQueue();
});
}
So, how can I change the url ? I dont know what to do here.
Thank you! :)
There is a page on the dropzone wiki that shows you how to do this. I'm typing it out here for posterity. You can take advantage of the processingfile event to set the upload url.
<form id="my-dropzone" action="/some-url" class="dropzone"></form>
<script>
Dropzone.options.myDropzone = {
init: function() {
this.on("processing", function(file) {
this.options.url = "/some-other-url";
});
}
};
</script>
I have an application which uses backbone hash routing. When the page reloads I use the onbeforeunload event to tell the user that there are unsaved changes and prevent the page load. This does not work on hash change; so if the user presses back the dialog does not tell them there are changes pending and just goes back.
Is there anyway to detect the hash change and prevent it happening? something like onbeforehashchange
Nope, you can detect the hashchange as it happens with something like below, but you can't really detect it before it happens. If you need the hash before it changes you can just store it somewhere.
var myHash = document.location.hash;
$(document).on('hashchange', function() {
if (myHash != document.location.hash) {
//do something
}
});
You can't really detect the back button either, and if it does'nt trigger a reload, onbeforeunload won't work either.
If this functionality is essential, you should consider trying the haschange plugin or the history plugin, as one of those would make this a lot easier, and let you control the browser history and back/forth.
I ended up creating a function in my router. This is run before each route and puts up a jquery ui dialog and waits for a reply to run the route. This is quite messy code a I stripped out the application specific stuff.
close: function(callback) {
var hash = window.location.hash;
if (this.afterHash && this.afterHash == hash) {
this.dialog.dialog("close");
return;
}
callback = callback || function () {};
if (window.onbeforeunload) {
var text = window.onbeforeunload();
if (text) {
if (!this.dialog) {
var t = this;
this.afterHash = this.previous;
this.dialog = $("<div><p>" + text + "</p><p>Are you sure you want to close the dialog?</p></div>").dialog({
modal: true,
width: 420,
title: "Confirm Navigation",
close: function() {
t.dialog.dialog("destroy");
if (t.afterHash) {
t.navigate(t.afterHash, {
trigger: false
});
t.afterHash = null;
}
t.dialog = null;
},
buttons: {
'Leave this Page': function() {
t.afterHash = null;
t.dialog.dialog("close");
closeViewer();
callback.apply(t);
},
'Stay on this Page': function() {
t.dialog.dialog("close");
}
}
});
}
return;
}
}
this.previous = window.location.hash;
callback.apply(this);
},
on initialize you must add this.previous = window.location.hash;
I have a form in a JSP as follows:
<form action = "<c:url value = '/displayVisualisation' />"
title = "${item.visDescription}"
method = "post" onClick = "return confirmRequest('Do you want to change to
another visualisation type?');">
<input class = "text" type = "text" value = "${item.visTypeName}">
</form>
Which calls a Javascript method as follows:
function confirmRequest(questionText) {
var confirmRequest = confirm(questionText);
if (confirmRequest) {
return true;
}
else {
return false;
}
}
To ask the user for a reply to the question asked. However, the confirm prompt appears but does not perform the displayVisualisation action!
Can anyone suggest why or help me implement this correctly?
In other examples, where the action is triggered by clicking a graphic, all is well.
Since you are using onclick, return true; in your confirmRequest function is simply allowing the rest of the clickHandler chain to be executed. I think you also need to explicitly submit the form at this time, in the true case.
Here is one way to do that, using only javascript:
function confirmRequest(questionText) {
var confirmRequest = confirm(questionText);
if (confirmRequest) {
document.forms[0].submit();
return true;
}
else {
return false;
}
}
I'd like to learn how to bind a CNRTL-S or COMMAND-S to call a function that I have on my page which AJAX saves the textarea content's
How can I bind those two commands? I used to use the following when it was just a textarea, but since adding TinyMCE it no longer works. Suggestions?
// Keybind the Control-Save
jQuery('#text_area_content').bind('keydown', 'ctrl+s',function (evt){
saveTextArea();
return false;
});
// Keybind the Meta-Save Mac
jQuery('#text_area_content').bind('keydown', 'meta+s',function (evt){
saveTextArea();
return false;
});
Thanks
To use a custom method for saving, i declare my saving function in the tinymce.init method
tinyMCE.init({
// General options
mode: "none",
/* some standard init params, plugins, ui, custom styles, etc */
save_onsavecallback: saveActiveEditor,
save_oncancelcallback: cancelActiveEditor
});
Then i define the function itself
function saveActiveEditor() {
var activeEditor = tinyMCE.activeEditor;
var saveUrl = "http://my.ajax.path/saveStuff";
var idEditor = activeEditor.id;
var contentEditor = activeEditor.getContent();
/* the next line is for a custom language listbox to edit different locales */
var localeEditor = activeEditor.controlManager.get('lbLanguages').selectedValue;
$.post(saveUrl ,
{ id: idEditor, content: contentEditor, locale: localeEditor },
function(results) {
if (results.Success) {
// switch back to display instead of edit
return false;
}
else {
activeEditor.windowManager.alert('Error saving data');
return false;
}
},
'json'
);
return false;
}
Don't forget to return false to override the default save action that posts back your data to the server.
edit to add: i only let the user change one tinymce instance at a time. You may want to change the locating the current instance to something else :)
edit #2: TinyMce already catches the Ctrl+s binding to process the data. Since it also cleans up html and is able to handle specific rules it's given when saving, the solution i propose is to plug your way of saving in tinyMce instead of fully overriding the Ctrl+s binding
The problem here is that the tinymce iframe does not delegate the events to the parent window. You can define custom_shortcuts in tinymce and/or use the following syntax:
// to delegate it to the parent window i use
var create_keydown_event = function(combo){
var e = { type : 'keydown' }, m = combo.split(/\+/);
for (var i=0, l=m.length; i<l; i++){
switch(m[i]){
case 'ctrl': e.metaKey = true;
case 'alt': case 'shift': e[m[i] + 'Key'] = true; break;
default : e.charCode = e.keyCode = e.which = m[i].toUpperCase().charCodeAt(0);
}
}
return e;
}
var handler = function(){
setTimeout(function(){
var e = create_keydown_event(combo);
window.parent.receiveShortCutEvent(e);
}, 1);
}
//ed.addShortcut(combo, description, handler);
ed.addShortcut('ctrl+s', 'save_shortcut', handler);
in the parent window you need a function receiveShortCutEvent which will sort out what to do with it