Refresh SlickGrid via call to JsonResult after initial load - json

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

Related

Action buttons in ASP.NET Core 2.2 razor view

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.

accessing angularjs textbox value in a controller

I am trying to learn AngularJS and require help in passing user entered text box text value after button click to append to a string url value while calling the http service.
I'm trying to add in the following way but it is showing me a value of undefined while appending the URl with the user entered text from the text box.
Here is my HtmlPage1.html
<form ng-submit="abc(inputValue)">
<input type="text" name="name" ng-model="inputValue" />
<button type="submit">Test</button>
</form>
and my script file Script.js
var app = angular.module("repos", [])
.controller("reposController", function ($scope, $http, $log) {
$scope.inputValue = null;
$scope.abc = function (value) {
$scope.inputValue = value;
};
$http({
method:'GET',
url: 'https://api.github.com/users/'+$scope.inputValue+'/repos'
})
.then(function (response) {
$scope.repos = response.data;
$log.info(response);
});
});
Can anyone help me in this regard on how to get the right value that the user has entered to appended to the URL?
Thanks in advance.
Your get call is placed before you enter any value. In order to call the API with inputValue, place the get call inside the button click.
Also, you do not have to pass the inputValue into the function from HTML, Angular's 2 way binding will do the job for you.
Ex:
HTML
<form ng-submit="abc()">
<input type="text" name="name" ng-model="inputValue" />
<button type="submit">Test</button>
</form>
JS:
var app = angular.module("repos", [])
.controller("reposController", function ($scope, $http, $log) {
$scope.inputValue = null;
$scope.abc = function () {
$log.info($scope.inputValue) // you will have your updated value here
$http({
method:'GET',
url: 'https://api.github.com/users/'+$scope.inputValue+'/repos'
})
.then(function (response) {
$scope.repos = response.data;
$log.info(response);
});
});
};
I hope this helps.
Just remember that you have the code on your controller thanks to 2 way binding.
There you will set up an object for models. Ad later you can use them to submit data.
In order for you to understand what I am trying to explain I made an example, I hope it Helps
In your code:
Set the ng-model on the input tag
<input type="text" name="name" ng-model="vm.data.inputValue" />
On your controller make it available as in my example
vm.data ={};
Then use a function to send it using ng-click.
<button type="submit" ng-click="vm.submit()">Test</button>
I am sure there are more ways to do this.
I am not that good, explaining so I made an example, that I hope helps:
https://jsfiddle.net/moplin/r0vda86d/
my example is basically the same but I prefer not to use $scope.

How do i get input form value without submitting it?

I want the input value from user without submitting any thing then i want to pass it through ajax method as parameter to action method. I tried many method but i could not found a solution.
Here is the code
<input type="text" id="task" name="task" value="" />
#Ajax.ActionLink("ADD TASK", "show_task",new {task=Request["task"]}, new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "print",
InsertionMode = InsertionMode.Replace
})
Here is the controller action method
public ActionResult show_task(string task)
{
var add_task = new tasks_table();
add_task.task = task;
add_task.id = 24;
add_task.f_id=10;
add_task.date_oftask=DateTime.Now;
db.tasks_table.Add(add_task);
db.SaveChanges();
var tasks = db.tasks_table.Include(t => t.user_detail);
return PartialView("render_tasks",tasks);
}
Since you want the current value of the textbox, you may better do it yourself with your own javascript code to make the ajax call, instead of relying on the Ajax.ActionLink helper method.
So change your Ajax.ActionLink call to a normal action link.
<input type="text" id="task" name="task" value="" />
#Html.ActionLink("Add Task","show_task", null, new {id="addTask"})
<div id="print"></div>
Now listen to the click event on this link, read the value of the text box and send that to your server. You may use jQuery $.post method to do so. In the response callback, you can update the print div's content with the response coming back from your server.
$(function(){
$("a#addTask").click(function(e){
e.preventDefault();
$.post($(this).attr("href"), { task:$("#task").val()},function(res){
$("#print").html(res);
});
});
});
You can use JavaScript focusOut function to send the value to controller.
by focusOut method, we get the value in input field instantly when we moved to next field.
$('#task').focusOut(function(){
Your ajax call method....
});
Hopes it helps.

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

knockout issue with deleting from observable array

I'm having data binding a knockout function to my html.
Following is the view model:
var DonutViewModel = function () {
this.donuts = ko.observableArray();
//donutData = JSON.parse(donutData);
var items = $.map(donutData, function (data) { return new Donut(data) });
this.donuts(items);
this.deletedonut = function (item) {
this.donuts.remove(item);
}
}
var viewModel;
$(document).ready(function () {
viewModel = new DonutViewModel();
ko.applyBindings(viewModel);
});
following is the html:
<tr>
<td><input id="txtdonutid" type="text" data-bind="value:id"/></td>
<td><input id="txtdonuttype" type="text" data-bind="value:type"/></td>
<td><input id="txtdonutname" type="text" data-bind="value:dname"/></td>
<td><input id="txtppu" type="text" data-bind="value:ppu"/></td>
<td><input type="button" value="Delete Donut" data-bind="click: function() {$parent.deletedonut($data)}"/></td>
</tr>
Notice how I have data-bound the delete function and THIS WORKS!. but if I do the following:
<td><input type="button" value="Delete Donut" data-bind="click: {$parent.deletedonut($data)}"/></td>
well, this doesn't work. The delete function doesn't even get hit.
Can someone tell me what I'm doing wrong?
You only need to the function() ... syntax in your click binding if you want to pass additional parameter to your handler beside the $data. (see the documentation: Accessing the event object, or passing more parameters section)
But if your only parameter is $data then KO will automatically pass that in so you can just write:
<input type="button" value="Delete Donut"
data-bind="click: $parent.deletedonut"/>
Note: there is no need for the {} and you also don't need arguments as well ($data) because you are passing the $parent.deletedonut as the reference to that handler function.
But in itself this won't work in your case because you are using this in your handler to access your view model.
You have two options:
You can use bind: data-bind="click: $parent.deletedonut.bind($parent)" in this case you don't need to change your handler.
Demo JSFiddle
Or you can store a reference of the this in a variable like self and use that in your handler instead of the this.
So change your handler to:
var self = this;
this.deletedonut = function (item) {
self.donuts.remove(item);
}
Demo JSFiddle.