Action buttons in ASP.NET Core 2.2 razor view - razor

Suppose we're redesigning the view below:
The current code is:
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Url)
</td>
<td>
<a asp-action="Edit" asp-route-id="#item.BlogId">Edit</a> |
<a asp-action="Details" asp-route-id="#item.BlogId">Details</a> |
<a asp-action="Delete" asp-route-id="#item.BlogId">Delete</a>
</td>
</tr>
}
Our goal is to remove the Delete view that is linked in each row. Instead we would like to have a delete button that deletes the row upon confirmation without leaving the Index page (reload is fine).
How would one go about implementing such button? And is there any relevant documentation?

You can use ajax to issue a delete request so that user can stay during the deletion process. Once the ajax request is successful,you can remove the table row from the UI.
First, add a new attribute to your anchor tag, which you can use for your jQuery selector to wire up the click event.
<a asp-action="Delete" ajaxy asp-route-id="#item.BlogId">Delete</a>
Here I added an attribute called ajaxy
Now we will listen to the click event on anchor tags with this ajaxy attribute, stop the normal behavior( navigating to the href attribute value URL) and instead make an ajax call. To do the confirmation, you can use window.confirm API.
#section Scripts
{
<script>
$(function () {
$("a[ajaxy]").click(function (e) {
e.preventDefault();
if (window.confirm("Are you sure ?")) {
var $this = $(this);
var url = $this.attr("href");
$.post(url).done(function (res) {
$this.closest("tr").fadeOut(300, function (a) {
$(this).remove();
});
}).fail(function (jqXHR, textStatus, errorThrown) {
alert("error in ajax call!" + errorThrown);
})
}
});
});
</script>
}
Assuming your Delete action accepts the Id parameter.
[HttpPost]
public async Task<IActionResult> Delete(int id)
{
// to do : return something
}

If you just want to remove the extra 'delete' view, you can move the delete code from the delete page tot he index page and use a simple html-form. e.g.
<form method="post" asp-page-handler="Delete" class="btn-group-sm" >
<a asp-page="./Edit" asp-route-id="#item.Id" class="btn btn-warning">Edit</a>
<a asp-page="./Details" asp-route-id="#item.Id" class="btn btn-info">Details</a>
<input type="hidden" asp-for="#item.Id" />
<input type="submit" value="Delete" class="btn btn-danger" onclick="return confirm('Are you sure you wish to delete this q-Section?')" />
</form>
Rename the 'OnPost' function to 'OnPostDelete' and it will work. You can do the same for the 'delete' button on the details page.
Regards Ken.

Related

Refresh SlickGrid via call to JsonResult after initial load

I have setup a MVC webpage with a SlickGrid and can populate it upon initial page load. My javascript for loading:
$.getJSON("../Home/GetSlickGridData",
function(data) {
dataView.beginUpdate();
//dataView.setItems(data);
dataView.setItems(data, "OrderID");
dataView.setFilterArgs({
searchString: searchString,
searchShipmentID: searchShipmentID,
searchDestination: searchDestination,
searchCarrier: searchCarrier
});
dataView.setFilter(myFilter);
dataView.endUpdate();
});
This calls a controller action:
public JsonResult GetSlickGridData()
{
The issue now is that I'm unsure of how to refresh the grid when a search criteria is added to the cshtml page's search form:
#using (Html.BeginForm("GetSlickGridData", "Home"))
{
<table>
<tr>
<td>Shipper</td>
<td><input type="text" name="myText" id="txtShipper" /></td>
<td><input type="submit" value="Filter" onclick="GetData"></td>
</tr>
</table>
}
Can I use the loading for initial page load and for a search?
UPDATE:
Based on #Steve T's answer:
The search:
> <input type="text" name="myText" id="txtShipper" />
> <input type="button" value="Filter" onclick="GetData()">
The jquery:
function GetData() {
Slick.GlobalEditorLock.cancelCurrentEdit();
grid.invalidateAllRows();
var searchText = $("#txtShipper").val();
$.getJSON("../Home/GetSlickGridData?search=" + searchText,
function (data) {
The controller:
public JsonResult GetSlickGridData(string search)
And the map route (to ensure the controller works):
routes.MapRoute("search", "Home/GetSlickGridData/{search}",
new {Controller = "Home", Action = "GetSlickGridData"});
Instead of submitting the form and reloading the whole page you can change the filter button to type="button" and then use the GetData() function (not sure if you have this already implemented) to repeat the initial $.getJSON call with the value of text field txtShipper as a parameter

A href go on next page when i click on star rating input

On my page I have a table. In the table there is one td, in which I am showing average rating input. I want when I click on average rating page, the href goes to next page.
Can anyone tell me how it can be possible?
Here is my html, but it doesn't work.
<table>
<tr>
<td><a href='supp_view_screen.php?id=$encrypt_id'><input id='rating-input' type='number' readonly value='".$last_cal."' step='1' class='rating'/></a></td>
</tr>
</table>
Use this code snippet for that :
<table>
<tr>
<td><a href='supp_view_screen.php?id=$encrypt_id' target='_blank'><input id='rating-input' type='number' readonly value='".$last_cal."' step='1' class='rating'/></a></td>
</tr>
</table>
A good rule of thumb is:
If there is no meaningful href, then it's a button
In your case, the element can either be a <button> element, a span, or even an image.
What I'm saying is that using a href here is not correct. What you're better off doing is using an ajax call to get the data from your controller.
$('#rating-input').click(function (e) {
"use strict";
e.preventDefault();
$.ajax({
data: user,
method: 'POST',
url: 'supp_view_screen.php?id=$encrypt_id',
done: function () {
//Do something after its done
},
success: function (data) {
//Append your data to the DOM
},
error: function (xhr, status) {
//Do something on error
}
});
});
preventDefault will need to be used if you are using a <button> inside a <form> or an <input> with the type of submit.

Watching jQuery click event for HTML button (not input)

I have been doing some searching and most of what I find relates to the html <input type="submit"> buttons or connecting to a button by the ID tag. What I am trying to do is attach to every html5 <button> based off the NAME tag.
I have tried the following but when the button is clicked it submits and I don't get any alerts before it does.
$("button[name=Submit]").click(function ()
{
var error;
alert("test1");
if ($("#SelectedProjectCodes").val() == "") { alert("test"); }
return false;
});
Also tried
$("input[name=Submit]").click(function ()
{
var error;
alert("test1");
if ($("#SelectedProjectCodes").val() == "") { alert("test"); }
return false;
});
Here is the HTML for one of the submit buttons:
<button formnovalidate="formnovalidate" type="submit" name="Submit" value="Add Time">Add Time</button>
So how am I supposed to attach to all my html5 buttons?
Note: The JS in in an external file with about a dozen other functions which all work so I do know the JS file is being loaded properly and working. And all the code is in a $(document).ready(function ()
You need to prevent the default behaviour:
$("button[name=Submit]").click(function(event) {
event.preventDefault();
// other code
});
You must put the id in the button like below
<button formnovalidate="formnovalidate" id="id1" type="submit" name="Submit" value="Add Time">Add Time</button>
And also you jquery code sometime like this (call via button id)
$( "#id1" ).click(function() {
var error;
alert("test1");
if ($("#SelectedProjectCodes").val() == "") { alert("test"); }
return false;});
Hope it helps you...

How to create a submit button with ui-sref in angular

I have a multi-step form, each step having a btn-link to move to the next step. I achieve this with angular routes in this way:
<button ui-sref="next.step" class="btn btn-link"></button>
In one of the steps in the middle of the whole form I need to submit the data, so I need the already described button to submit the form as well and only if the form could be submitted then move to the next step.
I tried doing this but it is not working because it redirects to the next step without taking care about the form
<button ui-sref="next.step2" type="submit" class="btn btn-link"></button>
How can I achieve this using angular?
you don't need to use ui-sref for your next button instead use $state service from your controller as shown below
HTML Code
<form ng-submit="onFormSubmission($event)">
<button type="submit" class="btn btn-link"></button>
</form>
Controller
var successCallback = function(response) {
//process response
$state.go("next.step2");
}
$scope.onFormSubmission = function($event) {
var data = getFormData();
$http.post('/someUrl', data, config).then(successCallback, errorCallback);
}
Use ng-submit to submit the form and show some loading message as form is getting saved, use $http to post the data and on-success take user to next route using $state.go.
<script>
angular.module('submitExample', [])
.controller('ExampleController', ['$scope', '$state', function($scope, $state) {
$scope.list = [];
$scope.text = 'hello';
$scope.submit = function() {
$http.get('/aveData', config).then(function(response){
$state.go('next.step2')
}, function(){
alert('error saving data');
});
};
}]);
</script>
<form ng-submit="submit()" ng-controller="ExampleController">
Enter text and hit enter:
<input type="text" ng-model="text" name="text" />
<input type="submit" id="submit" value="Submit" />
</form>

MVC 5 prevent page refresh on form submit

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"
);
}