In my MVC5 web app, I have a textbox that I key comment text into then click a button to add the comment. JavaScript ajax fires off the controller action method that adds the comment to the database returns a partial view with the added comment. Then it rebuilds the HTML. At that point, just want to remove the content that was keyed into the textbox.
Here's the ajax call and where I try to reset the textbox using:
document.getElementById("comment_1").innerText = "Add a Comment Again ...";
.
// For when clicking the addComment button. Adding a new comment.
$('.addComment').on('click', function () {
var postId = $(this).attr('data-id');
var commentMsg = $('#comment_' + postId).val();
var dateTimeNow = new Date();
// An object.
var comment = {
CommentMsg: commentMsg,
CommentedDate: dateTimeNow.toLocaleString()
};
// Call the Comments controllers action method to get add a comment related to the post id. Will show a partial view.
$.ajax({
type: 'POST',
url: '#Url.Action("AddComment", "Comments")',
data: { comment, postId },
success: function (response) {
$('div[class=allComments_' + postId + ']').remove();
// Dynamically building the HTML to hold the comments returned which now includes the added comment.
// The area for the Shared/_MyComments.cshtml to be placed.
var allCommentsArea = $('<div>').addClass('allComments_' + postId);
allCommentsArea.html(response);
allCommentsArea.prependTo('#commentsBlock_' + postId);
// Reset the value in the input textbox.
document.getElementById("comment_1").innerText = "Add a Comment Again ...";
},
error: function (xhr, ajaxOptions, thrownError) {
alert("Critical Error: something is wrong in the call to AddComment! Status: " + xhr.status + ". Error: " + thrownError.toString() + ". Response Text: " + xhr.responseText);
}
});
});
Here's the textbox - whose id will become "comment_1":
<div id="#string.Format("{0}_{1}","commentsBlock", post.PostID)" style="border: 1px solid #f1eaea; background-color: #eaf2ff;">
<div class="AddCommentArea" style="margin-left: 30%; margin-bottom: 5px; margin-top: 8px;">
<input type="text" id="#string.Format("{0}_{1}", "comment", post.PostID)" class="form-control" placeholder="Add a Comment ..." style="display: inline;" />
<button type="button" class="btn btn-default addComment" data-id="#post.PostID"><span class="glyphicon glyphicon-comment" aria-hidden="true"></span></button>
</div>
</div>
Here's the resulting page after I attempt to reset the text box to a different value then I had keyed in.
I does not remove the text I keyed in.
I tried .innerText, .innerHTML and .TextContent
Test result from suggestion:
What you are doing is setting the text of the input to be "Add a Comment Again.." when you really want to be clearing the input text + making the placeholder "Add a Comment Again..". Try changing this code
// Reset the value in the input textbox.
document.getElementById("comment_1").innerText = "Add a Comment Again ...";
to this:
// Reset the value in the input textbox using jquery.
$("#comment_1").val('')
document.getElementById("comment_1").placeholder = "Add a Comment Again ...";
This way, you both clear the old text and also make the placeholder what you want it to be.
Related
So I can see the info of a user in a FullCalendar that is opened in a modal but when I try to open another the modal it doesn`t refresh. I tried all the solutions I found here on Stackoverflow but it didn't work. If I refresh the page then it works if I click in a diferent id.
Code where I bring the id of user to my function cale():
<button id="cal" onclick="cale('.$row["idutilizador"].') class="btn" data-toggle="modal" href="#calendario"><i class="fa fa-calendar"></i></button>
My calendar modal Bootstrap:
<div class="modal fade" id="calendario" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Calendario</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<br />
<h2 align="center">Calendario</h2>
<br />
<div class="container">
<div id="calendar"></div>
</div>
</div>
</div>
</div>
</div>
My function that loads the information from database with the id I got when I click:
function cale(uti){
var calendar = $('#calendar').fullCalendar({
editable:true,
header:{
left:'prev,next today',
center:'title',
right:'month,agendaWeek,agendaDay'
},
events: {
url:'../Components/calendar/load.php',
type: 'POST',
data: function() {
return {
id: uti
};
}
},
...
Your code currently reinitialises the calendar every time you click a button. You should only initialise the calendar once, and then change the data it displays. To do that, you need to first remove the previous event source, add the new one, and then get the new events.
A suggestion: convention is that POST is for changing data (eg making a purchase, updating a record), while GET is for reading data. Here your event source is just loading event data to display, that really should be a GET request. Changing that also makes the code a bit simpler. I've changed to GET here, if you want to do this you need to change your PHP to respond to GET instead of POST.
Another suggestion: AFAICT you are using multiple non-unique HTML IDs on the same page. Your code suggests that the button is inside a loop, so you have buttons for multiple users, but your buttons all have the same ID:
<button id="cal" ...
The code you've shown does not use that ID, but if you try to, it won't work. IDs must be unique, if they are not and you try to use them, only the first one will work.
Another suggestion: it is generally considered best to separate your JS and your HTML, so instead of using inline onclick, use a separate event handler. You'll need to add the user ID to the button somehow, maybe with a data attribute:
<button data-id="' . $row["idutilizador"] . '" ...
And then instead of onclick() on that button, add an event handler in your JS:
$('button').on('click', function(e) {
// Prevent any default action the button click might normally
// do, eg submit a form or something.
e.preventDefault();
// Find the ID of the clicked button
var userID = $(this).data('id');
// Now call the calendar function with that ID
cale(userID);
});
The code below implementes all these suggestions.
UPDATE As per comments you're using FullCalendar v3, so here's a working v3 solution (click Run to see it in action). I've also converted the previous v5 solution into a working snippet, see below.
FullCalendar v3 solution
// The base URL where your events are. I'm using npoint JSON
// bins from https://www.npoint.io/, yours would be:
// var sourceURL = '../Components/calendar/load.php';
var sourceURL = 'https://api.npoint.io/';
// The current source (none initially)
var currentSource;
// The calendar
var calendar = $('#calendar').fullCalendar({
defaultDate: '2022-01-15',
editable:true,
header:{
left:'prev,next today',
center:'title',
right:'month,agendaWeek,agendaDay'
},
// no events initially
});
// Handle button clicks
$('button').on('click', function(e) {
// Prevent any default action the button click might normally
// do, eg submit a form or something.
e.preventDefault();
// Find the ID of the clicked button
var userID = $(this).data('id');
// Now call the calendar function with that ID
cale(userID);
});
// Update sources
function cale(uti) {
// First remove the current source. First time through
// there is no source, but that does not matter.
// v3: https://fullcalendar.io/docs/v3/removeEventSource
calendar.fullCalendar('removeEventSource', currentSource);
// Set up the URL to the new source. I'm using npoint JSON
// bins from https://www.npoint.io/, so this URL format is
// different to yours, you would use:
// currentSource = sourceURL + '?id=' + uti
currentSource = sourceURL + uti;
// Now add the new source. Note this will use a GET request
// to retrieve events. The new events will be immediately
// fetched and displayed.
// v3: https://fullcalendar.io/docs/v3/addEventSource
calendar.fullCalendar('addEventSource', currentSource);
}
hr {
margin: 20px 0;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.4.0/fullcalendar.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.4.0/fullcalendar.min.js"></script>
Click to select a source:
<button data-id="965e830c3e8ab78990c5">Source 1</button>
<button data-id="5c8901e5173d5eab3ad6">Source 2</button>
<hr>
<div id="calendar"></div>
FullCalendar v5 solution
And here's the original v5 solution, as a working snippet, click Run to see it working.
// The base URL where your events are. I'm using npoint JSON
// bins from https://www.npoint.io/, yours would be:
// var sourceURL = '../Components/calendar/load.php';
var sourceURL = 'https://api.npoint.io/';
// The current source (none initially)
var currentSource;
// The calendar
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
initialDate: '2022-01-15',
editable:true,
// no events initially
});
calendar.render();
// Handle button clicks
$('button').on('click', function(e) {
// Prevent any default action the button click might normally
// do, eg submit a form or something.
e.preventDefault();
// Find the ID of the clicked button
var userID = $(this).data('id');
// Now call the calendar function with that ID
cale(userID);
});
// Update sources
function cale(uti) {
// First get all the current event sources
// v5: https://fullcalendar.io/docs/Calendar-getEventSources
var sources = calendar.getEventSources();
// Now remove those event sources. Note the first time through there
// are none.
// v5: https://fullcalendar.io/docs/EventSource-remove
for (const source of sources) {
source.remove();
}
// Set up the URL to the new source. I'm using npoint JSON
// bins from https://www.npoint.io/, so this URL format is
// different to yours, you would use:
// currentSource = sourceURL + '?id=' + uti
currentSource = sourceURL + uti;
// Now add your new source. Note this will use a GET request to
// retrieve events. The new events will be immediately fetched
// and displayed.
// v5: https://fullcalendar.io/docs/Calendar-addEventSource
calendar.addEventSource(currentSource);
}
hr {
margin: 20px 0;
}
<link href="https://cdn.jsdelivr.net/npm/fullcalendar#5.10.1/main.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/fullcalendar#5.10.1/main.min.js"></script>
Click to select a source:
<button data-id="965e830c3e8ab78990c5">Source 1</button>
<button data-id="5c8901e5173d5eab3ad6">Source 2</button>
<hr>
<div id="calendar"></div>
Try to empty first the div
$('#calendar').html('');
obviously first of
var calendar = $('#calendar').fullCalendar({...
i have an array of inputs generated upon a press of a button. the index is maintained using a global variable numInput set to 0. This is the first HTML of the input.
<label><span>First name</span>
<input placeholder="First name" type="text" name="fName[0]" id="fName"></label>
This is the addmore button, which increments numInput and appends the new and mostly the same HMTL with different index
$(document).on('click','#addmore',function(){
numInput++;
var html = '<label><span>First name</span>
<input placeholder="First name" type="text" name="fName['+numInput+']" id="fName"></label>';
$("#frm").append(html);
rerunRules();
});
Here is my validate method. I did not create the message object here...
$(document).ready(function() {
$('#frm').validate({
highlight: function(element, errorClass) {
$(element).fadeOut(function() {
$(element).fadeIn();
});
},
errorPlacement: function(error, element) {
error.appendTo(element.prev("span"));
},
});
});
rerunRules();
instead I changed the defaults:
<script>
jQuery.extend(jQuery.validator.messages, {
required: "- This field is required."
});
</script>
The rerunRules() is a function that I had to call to "reinject" the rules everytime a new HTML is generated. It is also called right after validate() because the fName rules are in it.
function rerunRules(){
$.each( $('input[name^="fName"]'), function () {
$(this).rules('add', {
required: true
})
});
}
Contrary to what I expected, the error message appears on the first fName[0] just as where its meant to be (to the previous span) but doesnt appear on the next generated HTML from the button. The validate works (wont proceed when I dont enter proper data), the highlight works, but no error message.
my initial HTML
<div class="p-10 p-chat-box">
<div class="input-group">
<span class="input-group-addon">
<img src="assets/images/emojis/1f603.png" class="letter-icon">
</span>
<p class="lead emoji-picker-container"><input id="readyforchat" data-emojiable="true" type="text" class="form-control" placeholder="Add a message ..."></p>
</span>' + attachMentList + '<span style="cursor:pointer;" onclick=NewsWidget.startchat(event) class="input-group-addon">
<i class="icon-arrow-right6"></i>
</span>
</div>
</div>
i am using emojji.js for generating emoji in text box with data-emojiable="true" property html will look like after applying(emojiable="true") this property on input type="text"
From FavoriteWeb LinkWrite a NotePick a filePhoto from gallery
with the id of "readyforchat". BUT my problem is that the jQuery keypress event not working on this id "readyforchat".please help me how can i achieve this.
Thanks in advance.
Please Add this code .
chat_form is claas of your form and chat_box is your chat input field class.
<script type="text/javascript">
$('.comment_reply_form').on('keydown', '.chat_box', function (e)
{
var key = e.which;
switch (key) {
case 13: // enter
//your code here
break;
default:
break;
}
});
</script>
for onkey event please modify your emojiarea.js file and replace 323 line with this code
this.$editor = $('<div onkeydown="comment(this,event)">').addClass('emoji-wysiwyg-editor').addClass($($textarea)[0].className);
Call function
<script type="text/javascript">
function comment(a,event){
var key = event.which;
if(key==13){
event.preventDefault(event);
//your code
}
}
</script>
I had a similar issue and solved it using the parent div:
$('#message-zone-inner').on('keyup', function(e) {
if (e.which == 13)
{
e.preventDefault();
$('#message-zone-inner button').click();
}
});
So basically it will monitor the parent div containing the input field, detect if enter has been pressed and click on the "Send" button automatically (you could also submit the form instead).
You have to add
"onkeypress": "return chatKeyPressed(event)"
in jquery.emojiarea.js in function this.$editor.attr at line 351
this.$editor.attr({
'data-id': id,
'data-type': 'input',
'placeholder': $textarea.attr('placeholder'),
'contenteditable': 'true',
"onkeypress": "return chatKeyPressed(event)"
});
Now you can add JavaScript function in your HTML like following
function chatKeyPressed(e) {
//key is pressed
}
which will be called when key is pressed in
<input id="readyforchat" />
I am showing a flash error message if a mobile number is not validated.
Flash message as "Mobile number not validated. click here to validate".
But I want to display the same error message with "click here" as the hyper link which will redirect me to the top of the page.
if (res.json.response.mobilevalidated == false) {
FlashService.Error("Mobile number not validated." + ( click here ) +" to validate", false);
$scope.disabled = function() {
$scope.model.disabled = true;
$scope.title = "Cannot access until mobile number is validated.";
}
} else {
$scope.model.disabled = false;
}
How can I use html tags inside the controller? As my error message is a dynamic one.
Use ng-include.
Js add
$scope.includePath = function () {
`templateUrl="..../your template path"`
};
HTML
<div ng-include="includePath" > New html is here </div>
Here in this case you can use <button> if you want to give click event.
HTML
<div ng-class="{ 'alert': flash, 'alert-success': flash.type === 'success', 'alert-danger': flash.type === 'error', 'selected': hlink}" ng-click = "linking()" ng-if="flash" ng-bind="flash.message" style="margin-top: 20px; ">
</div>
My Controller
if (res.json.response.mobilevalidated == false) {
$scope.linking = function(){
$location.path('/otp');
}
$scope.hlink =" click here";
FlashService.Error("Mobile number not validated." + $scope.hlink +" to validate" , false);
}
What you are looking for can be achieved using $sce that is included in Angular. Take a look at the Documentation here: https://docs.angularjs.org/api/ng/service/$sce
You basically define your HTML string as trusted in the Controller like this: $sce.trustAsHtml(Stackoverflow") and bind it in the template using ng-bind-html like <span ng-bind-html="mySuperCoolLink"></span>.
There is an example in the documentation liked above.
Edit:
Your function FlashService.Error receives an invalid string. You use string concatenation to include your HTML link, however, that only works if your HTML link is stored in a variable. So you have to do one of the following:
A)
FlashService.Error("Mobile number not validated. click here ) to validate", false);
or B)
var link = "( click here )";
FlashService.Error("Mobile number not validated." + link + " to validate", false);
In your provided code, the JS engine will recognise the round brackets as they are valid JS, but not the pointy brackets (I forgot their name...).
Edit 2:
Plunkr: https://plnkr.co/edit/WzzWtnJW98u3e7eTLn2q?p=preview
yBrowser: IE9
Technologies: MVC5
I am mainly using Angular for everything on my page. (Single Page App).
But because I am working with IE9, I can't use FileAPI.. So, I decided to go with MVC's Form Actions to get HttpPostedFileBase in my controller methods to handle fileupload.
Html Code: (Is present in a modal)
#using (Html.BeginForm("UploadTempFileToServer", "Attachment", FormMethod.Post, new { enctype = "multipart/form-data", id = "attachmentForm" }))
{
<div>
<span id="addFiles" class="btn btn-success fileinput-button" ng-class="{disabled: disabled}" onclick="$('#fileUpload').click();">
<span>Add files...</span>
</span>
<input id="fileUpload" type="file" name="files" class="fileInput" onchange="angular.element(this).scope().fileAdded(this)" />
</div>
<div>
<span class="control-label bold">{{currentFilePath}}</span>
<input name="fileUniqueName" value="{{fileUniqueName}}" />
<input id="attachmentSubmit" type="submit" value="Upload File" />
</div>
}
MVC Controller:
public void UploadTempFileToServer(IEnumerable<HttpPostedFileBase> files, string fileUniqueName)
{
var folderPath = fileStorageFolder;
foreach (var file in files)
{
if (file.ContentLength > 0)
{
file.SaveAs(folderPath + fileUniqueName);
}
}
}
Question #1: Does anyone know of a way to send the HttpPostedFileBase data to the controller, without using form's submit action?
I don't mind using Jquery if need be. I have tried hijacking the form's submit action and that didn't work.
I tried sending the file control's data using non submit button event, but no luck there either.
If not:
Question #2 How do I prevent the page from going to /Attachment/UploadTempFileToServer after the execution of submit is completed?
To answer #2 (and assuming you're using jQuery):
$(document).on('submit', '#attachmentForm', function(event){
event.preventDefault();
// everything else you want to do on submit
});
For #1, unfortunately, unless a browser supports XMLHttpRequest2 objects (which I don't believe IE9 does), you can't send file data via ajax. There are plugins that let you submit the form to a hidden iframe, though. I think Mike Alsup's Form plugin has that ability: http://malsup.com/jquery/form/#file-upload
So, after much research and attempts. This is my solution:
Using https://github.com/blueimp/jQuery-File-Upload/wiki
HTML:
Earlier I was using a hidden file upload control and triggering its click via a span. But because of security issues a file input which is opened by javascript can't be submitted by javascript too.
<div class="col-md-7">
<div class="fileupload-buttonbar">
<label class="upload-button">
<span class="btn btn-success btnHover">
<i class="glyphicon glyphicon-plus"></i>
<span>Add files...</span>
<input id="fileUpload" type="file" name="files"/>
</span>
</label>
</div>
</div>
Javascript:
$('#fileUpload').fileupload({
autoUpload: true,
url: '/Attachment/UploadTempFileToServer/',
dataType: 'json',
add: function (e, data) {
var fileName = data.files[0].name;
var ext = fileName.substr(fileName.lastIndexOf('.'), fileName.length);
var attachment = {
AttachmentName: fileName,
Extension: ext
}
var fileUniqueName = id + ext;
//Sending the custom attribute to C#
data.formData = {
fileUniqueName: fileUniqueName
}
data.submit().success(function (submitData, jqXhr) {
attachment.Path = submitData.path;
//Add the attachment to the list of attached files to show in the table.
$scope.attachmentControl.files.push(attachment);
//Since this is not a direct angular event.. Apply needs to be called for this to be bound to the view.
$scope.$apply();
}).error(function (errorData, textStatus, errorThrown) {
});
},
fail: function (data, textStatus, errorThrown) {
}
});
C#:
public virtual ActionResult UploadTempFileToServer(string fileUniqueName)
{
//Getting these values from the web.config.
var folderPath = fileStorageServer + fileStorageFolder + "\\" + tempFileFolder + "\\";
var httpPostedFileBase = this.Request.Files[0];
if (httpPostedFileBase != null)
{
httpPostedFileBase.SaveAs(folderPath + fileUniqueName);
}
return Json(new
{
path = folderPath + fileUniqueName
},
"text/html"
);
}