Populating a modal with data-id - javascript

My goal is:
Click on a link
Open a modal
View information related to the row where the user clicked
Currently, my modal opens but it displays all my records, what I wish is simply to display the good record with the corresponding information.
I have a data-id on the <a> which is a unique identifier, I get it but I do not know how to use it later.
I also noticed with my Chrome debugger that when I open the modal it goes into shown.bs.modal but then it goes directly without executing what is in the function.
I do not know if this is really important in relation to my question but I would like to specify that my model contains a List <_Event>, _Event being a class that serves as a model for events.
Any help?
[Authorize]
[HttpGet]
public async Task<ActionResult> GetEventsDetails(int Zkp)
{
ViewBag.sessionv = HttpContext.Session.GetInt32("idMember");
FileMakerRestClient client = new FileMakerRestClient(serverName, fileName, userName, password);
var toFind = new Models.EventsLines { Zkp = 1392 };
var results = await client.FindAsync(toFind);
bool isEmpty = !results.Any();
if (isEmpty)
{
return View();
}
Models.EventsLines oEventViewModel = new Models.EventsLines();
oEventViewModel = results.ToList().First();
Console.WriteLine(oEventViewModel);
return PartialView(oEventViewModel);
}
function GetEventsDetails(id) {
$.get("#Url.Action("GetEventsDetails", "Events")/" + id,
function (data) {
$('.modal-body').html(data);
})
$('#myModal').show();
}

Related

How to retain Select value after ajax within a partial view?

In my ASP.NET Core web application I have a partial view that will need to be placed in several views and be able to respond to dynamic data that will vary based on the view that's rendering this partial at the time. The red box in the image blow represents the area the partial is rendered.
The partial is essentially a Select that will call a Stored Procedure and return a datatable and render out the table to the partial view. I am able to select an option on the page and have it call the SP and see all relevant data from the datatable and can write that out on the page no problem. The problem I am having is that every time the partial refreshes via ajax, the Select returns to the default "Select" value and does not keep the previously selected option selected.
For the sake of brevity, assume that the FeedbackQueries object just contains 4 string elements.
_FeedbackQueryResultPartial.cshtml
#using Contract.Shared;
#model FeedbackQueries
<style>
#select {
margin: auto;
text-align: center;
}
</style>
<div id="feedbackQueryResultPartial">
<div style="height:25px;">
<div id="select">
<select name="StoredProcs" id="StoredProcs" onchange="selectQuery()">
<option value="Select">Select</option>
#foreach (FeedbackQuery query in Model.Queries)
{
#Html.Raw($"<option value='{query.SprocName}'>{query.SprocName}</option>");
}
</select>
</div>
<div id="feedbackQueryDiv" class="row">
#if (Model.FeedbackQueryResults.Rows.Count > 0)
{
<h3>DataTable goes here</h3>
}
else
{
<h3>No rows were returned from your query. Please select another.</h3>
}
</div>
</div>
</div>
Processing.cshtml
#using Contract.Parent
#using Contract.Shared
#model Processing
<script>
function showFeedbackPartial(x, y, z, q) {
$.ajax({
cache: false,
url: '#Url.Action("GetFeedbackQueryDatatable", "Client")',
type: 'POST',
data: { databaseConnectionString: x, storedProcedure: y, page: z, Model: q },
success: function (result) {
var selected = $('#StoredProcs').val();
console.log(selected);
if (result.rowCount > 0) {
console.log(result.rowCount);
var databaseConnectionString = x;
var storedProcedure = y;
var page = z;
var model = q;
var url = '#Url.Action("ViewFeedbackQueryPartial", "Client")';
$("#feedbackQueryResultPartial").load(url, { databaseConnectionString, storedProcedure, page, model });
}
else {
document.getElementById('feedbackQueryDiv').innerHTML = '<h3>No rows were returned from your query. Please select another.</h3>';
}
$('#StoredProcs').val(selected);
$("#StoredProcs option[value='Select']").remove();
}
});
}
</script>
<script>
function selectQuery() {
var e = document.getElementById('StoredProcs');
var ev = e.options[e.selectedIndex].text;
var p = 'Processing';
var model = #Html.Raw(Json.Serialize(Model.FeedbackQueries));
console.log(model);
showFeedbackPartial('#Model.Client.DatabaseConnectionString', ev, p, model);
}
</script>
<script>
$(document).ready(function () {
document.getElementById('feedbackQueryDiv').innerHTML = '<h3>Select a query to view feedback.</h3>';
});
</script>
}
<form method="post" enctype="multipart/form-data">
...
<partial name="_FeedbackQueryResultPartial" for="#Model.FeedbackQueries" />
...
</form>
Controller actions that render the Processing view
[HttpGet]
public IActionResult Processing(int Id)
{
ViewBag.Id = Id;
Processing processing = new Processing();
//Get pertinent information for Client
processing.Client = _clientProcessingService.GetSingleClient(Id, _appSettings.MOPConfigConnectionString);
processing.Client.DatabaseConnectionString = _clientProcessingService.GetClientConnectionFromConfig(processing.Client, _appSettings);
processing.Steps = _clientProcessingService.GetClientSteps(processing.Client.DatabaseConnectionString, "Processing");
processing.CurrMoInfo.CurrMo = _clientProcessingService.GetProcessingCurrMo(processing.Client.DatabaseConnectionString);
processing.FeedbackQueries = _clientProcessingService.GetFeedbackQueriesFromDb(processing.Client.DatabaseConnectionString, "Processing");
return View(processing);
}
[HttpPost]
public IActionResult Processing(Processing Model)
{
//Get pertinent information for Client
Model.Client = _clientProcessingService.GetSingleClient(Model.Client.ClientID, _appSettings.MOPConfigConnectionString);
Model.Client.DatabaseConnectionString = _clientProcessingService.GetClientConnectionFromConfig(Model.Client, _appSettings);
Model.Steps = _clientProcessingService.GetClientSteps(Model.Client.DatabaseConnectionString, "Processing");
Model.CurrMoInfo.CurrMo = _clientProcessingService.GetProcessingCurrMo(Model.Client.DatabaseConnectionString);
Model.FeedbackQueries = _clientProcessingService.GetFeedbackQueriesFromDb(Model.Client.DatabaseConnectionString, "Processing");
return View(Model);
}
Controller action that renders the partial
public IActionResult ViewFeedbackQueryPartial(string DatabaseConnectionString, string StoredProcedure, string Page, FeedbackQueries Model)
{
if(StoredProcedure == "Select")
{
return PartialView("_FeedbackQueryResultPartial", Model);
}
Model.FeedbackQueryResults = _clientProcessingService.GetFeedbackQueryDataTable(DatabaseConnectionString, Page, StoredProcedure);
return PartialView("_FeedbackQueryResultPartial", Model);
}
I have tried so many different ways of maintaining this value. Adding it to the model, adding it to the Viewbag and countless other methods of attempting to retain this value somewhere and regardless of success or failure, keep the value and change it to the selected option via javascript. It resets to "Select" every time the partial is reloaded after the ajax call is made.
This also presents another problem wherein, when I submit the form on the Processing view by clicking RUN the page will refresh and go to the next step in the process but ideally what should also happen is that the value in the partial is kept, the query is ran again and the user doesn't need to select a new value at any point unless they want to run a different SP to see different data in the table.
Is this even possible or am I trying to do this the entirely wrong way?
For your issue, you may need to pass the selected SprocName from Parent View to partial view with Model.
Add SelectedSprocName to FeedbackQueries
public class FeedbackQueries
{
public string SelectedSprocName { get; set; }
public List<FeedbackQuery> Queries { get; set; }
public FeedbackQueryResults FeedbackQueryResults { get; set; }
}
Change View to set SelectedSprocName
function showFeedbackPartial(x, y, z, q) {
$.ajax({
cache: false,
url: '#Url.Action("GetFeedbackQueryDatatable", "Process")',
type: 'POST',
success: function (result) {
var selected = $('#StoredProcs').val();
model.SelectedSprocName = selected;
var url = '#Url.Action("ViewFeedbackQueryPartial", "Process")';
$("#feedbackQueryResultPartial").load(url,{ databaseConnectionString, storedProcedure, page, model });
console.log('after load' + selected);
// your rest code
}
});
}
Partial View set selected option
#foreach (FeedbackQuery query in Model.Queries)
{
if (query.SprocName == Model.SelectedSprocName)
{
#Html.Raw($"<option value='{query.SprocName}' selected='true'>{query.SprocName}</option>");
}
else
{
#Html.Raw($"<option value='{query.SprocName}'>{query.SprocName}</option>");
}
}

Populate data from groovy controller in pop up

I have a gsp page with a delete button for each row of a table. On the button click I want a pop up which tells the consequences of the delete. These consequences depends on the data present in the row and a few other constraints known to the grails service which is called from the grails controller associated to the gsp page. If the user confirms these consequences the row should be deleted from the table, else the table remains unchanged.
How should i go about to achieve this behavior?
Currently, I have in my gsp
<tr>
<td>name</td>
<td>parentName</td>
<td>data</td>
<td>
<g:link action="deleteRow" params="${[name: row.name, parentName: row.parentName]}">
<button class="deleteSnapshot">Delete</button>
</g:link>
</td>
</tr>
and in my .js file
$(document).on('click', ':button', function (e) {
var btn = $(e.target);
btn.attr("disabled", "disabled"); // disable button
alert('getting deletion details');
//var deletionDetails -->not sure how to get these
//var deletionDetails will get data from controller action:"getDetails"
if (confirm('/*print deletion details and ask*/ Do you want to proceed?')) {
alert('will delete')
return true
}
else {
btn.removeAttr("disabled"); // enable button
return false
}
});
and in my controller
class DeleteController{
DeleteService deleteService
def index() {
[list:deleteService.getTableList()]
}
def getDeletionDetails(string name, String parentName){
return deleteService.getDetails(name,parentName)
}
def deleteRow(String name, String parentName){
service.deleteRow(name, parentName)
redirect controller:"DeleteController", action:"index"
}
}
I know the deletion works fine, because it works even with in the current state. Just that the confirmation box asks Do you want to proceed, without displaying the details.
Any help on how i could achieve what I am looking for will be appreciated.
P.S. I am new to stackoverflow, so if i missed out on certain convention do let me know.
Thanks in advance.
I can think of two ways of doing it:
The first one is using ajax to both get deletion details and delete the row
Assuming that deleteService.getDetails(name, parentName) returns a String,
first you need to change an getDeletionDetails action so it renders the response:
def getDeletionDetails(String name, String parentName){
render deleteService.getDetails(name, parentName)
}
and change g:link-s to buttons in gsp:
<button data-name="${row.name}" data-parent-name="${row.parentName}">
Delete
</button>
In your .js then put:
$(document).on('click', ':button', function (e) {
var btn = $(e.target);
btn.attr("disabled", "disabled"); // disable button
var name = btn.data('name');
var parentName = btn.data('parentName');
$.ajax({
url: "/delete/getDeletionDetails",
data: {
name: name,
parentName: parentName
},
success: function (data) {
if (confirm(data + '\nDo you want to proceed?')) {
$.ajax({
url: '/delete/deleteRow',
data: {
name: name,
parentName: parentName
},
success: function (d) {
console.log("Success: " + d);
}
});
} else {
btn.removeAttr("disabled"); // enable button
}
}
});
});
What this code does is it sends an ajax call to /delete/getDeletionDetails, then uses its response (rendered by getDeletionDetails action in DeleteController) to show a confirmation alert. If user confirms the question, another ajax call is sent - now to deleteRow action of DeleteController - with parameters taken from data attributes of clicked button. If user cancels - nothing happens, except for reenabling a button.
Your deleteRow should only change the return statement - it also must render the response:
def deleteRow(String name, String parentName){
service.deleteRow(name, parentName)
render "You deleted an item $name - $parentName."
}
You don't need redirect here, because - thanks to using ajax - user will never leave delete/index. You can just display some kind of confirmation on page after successful ajax call.
The second option is to put deletion details in hidden fields or data- attributes in each row and then just retrieve them in js:
You can create a method getDeletionDetails() in row's domain class (presumably Row) that returns the details (using services in domain classes is not perfect, but is should work ok if the service is not very complex). Then, in your .gsp place:
<td>
<g:link action="deleteRow" params="${[name: row.name, parentName: row.parentName]}">
<button class="deleteSnapshot" data-details="${row.deletionDetails}">Delete</button>
</g:link>
</td>
You should then be able to get details in .js like this:
var deletionDetails = btn.data('details');

Using iterative variable from C# for loop in JavaScript function

On one of my pages I have a for loop to iterate through a list of "Projects" (which is the main model for my website) and display some of their data. The following code is nested in a table and the middle cells removed for redundancy.
foreach (var item in Model.Projects)
{
<tr>
<td>#Html.DisplayFor(modelItem => item.SubmissionNumber)</td>
<td>#Html.DisplayFor(modelItem => item.Status)</td>
<!-- and so on -->
<td>#Html.ActionLink("Detail", "DisplayDetails", new { id = item.ProjectID })</td>
</tr>
}
The "Detail" link in the last cell will ideally make a box pop up (I'm thinking of using a Modal via Bootstrap) containing all of the data for the project. The "DisplayDetails" controller action returns a partial view that presents this information, but since I'm not using JavaScript or anything to render the partial view on the current page it renders it as it's own unformatted page. This is the controller action:
[HttpGet]
public ActionResult DisplayDetails(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Project project = db.Projects.Find(id);
if (project == null)
{
return HttpNotFound();
}
return PartialView("~/Views/Projects/_Detail.cshtml", project);
}
Ideally I would pass the ID to the controller using AJAX like I did below (which is code from another page of my website, again edited to remove redudancy):
$("#show").on("click", function () {
$.ajax({
url: '/Projects/SearchTable',
type: "GET",
data: {
Line1: $('#' + '#Html.IdFor(m => m.Project.ProjectAddress.Line1)').val(),
// and so on
County: $('#' + '#Html.IdFor(m => m.Project.ProjectAddress.County)').val(),
}
}).done(function(partialViewResult) {
$(".wrapper").html(partialViewResult);
$(".wrapper").css('display', 'block');
});
});
And by doing this I can embed the partial view onto the current page instead of it opening as a new page. I'm just not sure how to pass the project ID for a specific row in the table as data to the controller. Is this even possible? If not is there another way to achieve the same result?
You can replace your ActionLink with this:
<td>Details</td>
Then,
$(".details").on("click", function (e) {
e.preventDefault();
var projectId = $(this).data('id');
// Make the AJAX call here...
});

asp.net - Manipulate Page Content

I was wondering if anyone could explain how to manipulate content for various sections of a page depending on if a button is clicked. I think what I am looking for is similar to an include in php. I wasnt sure if asp.net had a way to do the same (partial view?) or if bootstrap/jquery is the way to go. I've included a .png to illustrate what I am trying to do.
I would like section b's content to change based on what button is selected in section A. While not necessarily relevant to this question.. I then would like various user inputs in section B to manipulate existing content in section C.
In your controller, have an action that returns a PartialView:
public PartialViewResult MyPartial(string someText)
{
var model = new MyPartialModel {SomeStuff = someText};
return PartialView(model);
}
Create the model and partial view as you would any other:
public class MyPartialModel
{
public string SomeStuff { get; set; }
}
Partial View:
#model ExampleApp.Models.MyPartialModel
#Html.TextBoxFor(m => m.SomeStuff)
Then on your page you can load in your partial via ajax with jQuery:
<div>
<button type="button" id="load-partial">Load The Partial!</button>
</div>
<div id="section-b"></div>
#section Scripts{
<script>
$(document).ready(function () {
$('#load-partial').click(function () {
$.get('MyPartial', { sometext: "Hello!" }).done(function (data) {
$('#section-b').html(data);
});
});
});
</script>
}
Edit to answer comment:
If you don't want to instantiate a new model in the controller each time, you can pass the model (more or less) directly from the view.
In you controller, have a very simple action that accepts a model as a parameter and returns the partial view. Note the HttpPost attribute.
[HttpPost]
public PartialViewResult MyPartial(MyPartialModel model)
{
return PartialView(model);
}
The model's got more than one property this time:
public class MyPartialModel
{
public string Name { get; set; }
public int Age { get; set; }
}
The partial's pretty much the same, except it now displays the new properties of the model.
#model MVCPlayGround.Models.MyPartialModel
#Html.TextBoxFor(m => m.Name)
#Html.TextBoxFor(m => m.Age)
The jquery on the main page/view is very also similar, but uses POST instead of GET.
// these could be anything, from control on the page, or whatever
var name = "James";
var age = 30;
$(document).ready(function () {
$('#load-partial').click(function () {
// note that Name and the Age are the names of the properties in our model
$.post('MyPartial', { Name: name, Age: age }).done(function (data) {
$('#section-b').html(data);
});
});
});
This works because when data transmitted via POST, it's treated as form data, and when the controller's deciding which action to use it'll look at the parameters for the actions, and compare them to the form data available. The MyPartialModel contains properties that match the form data, so it chooses that action. There are other subtle rules, but that's basically it. Behind the scenes it'll still be instantiating a model in the controller, it's just in the framework, not in the code you've written.
Another edit
Having just re-read your comment I don't think I've answered it fully.
If you want to save the changes you've made in a partial view to the main view, have some hidden fields in the main view to hold this data.
<input type="hidden" id="name-holder" />
<input type="hidden" id="age-holder" />
And then when you want to store a value to them, just set the values with jquery:
$('#some-save-button-maybe').click(function(){
$('#name-holder').val($('id-of-name-on-partial').val());
$('#age-holder').val($('id-of-age-on-partial').val());
});
When you click on a the button to show a partial, send the appropriate data to the controller to render in the partial:
$('#load-partial').click(function () {
$.post('MyPartial', { Name: $('#name-holder').val(), Age: $('#age-holder').val() }).done(function (data) {
$('#section-b').html(data);
});
});
Hopefully that's what you need...
Yes there are partial views in MVC, and they are usually belong in the Views/Shared folder of your project and are prefixed with a _ (i.e. _MyPartial.cshtml.
As #AdamHeeg pointed out in the comments, there are many tutorials on the web about this kind of setup and many different ways to achieve what you are after.
Here is roughly how I might tackle it...
HTML
<nav>
#Html.ActionLink("Button 1", "GetSectionB")
</nav>
<section id="sectionB">
<!-- Content here -->
</section>
JavaScript
$('nav a').on('click', function (e) {
e.preventDefault();
$.get(this.href, function (html) {
$('#sectionB').html(html);
});
});
Controller
public PartialViewResult GetSectionB()
{
var vm = new MyViewModel();
//do stuff
return PartialView("_SectionB", vm);
}

use values submitted in a form to publish and subscribe results of a mongodb query in meteor

I want a user to be able to type 2 inputs into a form, hit submit, and have the database send back documents with field values that match the values that were typed into the form.
If I hard code values for 'name' and 'code' variables on the last line, I get the right results and everything renders fine. So I think the problem has to do with how I'm using the variables / variable scope, or something of that nature.
more detailed description below...
I am using Meteor.
I have a form with 2 input fields, for example, product and brand
I want to send a query of the following form:
PriceList.find({'name': name, 'brandCode': code});
I have a template that renders based on the results of this query. This relies on publishing the results of the query:
if (Meteor.isServer) {
Meteor.publish('byProductAndBrand', function(){
var name = product;
var code = brand;
return PriceList.find({'name': name, 'brandCode': code});
});
}
I'm trying to use Meteor.subscribe() to change dynamically based on the form inputs:
if (Meteor.isClient) {
Template.dataSelectionForm.events({
'submit form#addDataSelectionForm': function(event, template){
event.preventDefault();
product = template.find([name='product_name']).value;
brand = template.find([name='brandCode']).value;
}
});
Meteor.subscribe('byProductAndBrand');
}
Here's the relevant code (duplicates what I wrote above, but may be less annoying to read...)
PriceList = new Meteor.Collection('PriceList');
product = 'dummyProduct';
brand = 'dummyBrandCode';
if (Meteor.isClient) {
Template.dataSelectionForm.events({
'submit form#addDataSelectionForm': function(event, template){
event.preventDefault();
product = template.find([name='product_name']).value;
brand = template.find([name='brandCode']).value;
}
});
Meteor.subscribe('byProductAndBrand');
}
if (Meteor.isServer) {
Meteor.publish('PriceList', function(){
return PriceList.find();
});
Meteor.publish('byProductAndBrand', function(){
var name = product;
var code = brand;
return PriceList.find({'name': name, 'brandCode': code});
});
}
Pass params to Meteor.subscription :
if(Meteor.isServer){
Meteor.publish('byProductAndBrand', function(product, brand){
var name = product;
var code = brand;
return PriceList.find({'name': name, 'brandCode': code});
});
}
}
if (Meteor.isClient) {
Template.dataSelectionForm.events({
'submit form#addDataSelectionForm': function(event, template){
event.preventDefault();
product = template.find([name='product_name']).value;
brand = template.find([name='brandCode']).value;
var instance = Template.instance();
if(instance.byProductAndBrandHandle != null){
instance.byProductAndBrandHandle.stop();
}
instance.byProductAndBrandHandle = Meteor.subscribe('byProductAndBrand', product ,brand);
}
});
}
It seems to me that you would be better off using dependencies instead of subscriptions. This makes sense to me in this circumstance because only the one client viewing the page is looking at this particular price list, you are not publishing this price list for multiple users as far as I can tell.
For ex:
In declarations, before if(Meteor.isClient) and if(Meteor.isServer):
var byProductAndBrandDep = new Tracker.Dependency;
Inside of priceList helper:
byProductAndBrandDep.depend();
In "submit form#addDataSelectionForm".events: function(event, templates) {
byProductAndBrandDep.changed();
Then, every time the form is submitted, every helper that has the byProductAndBrandDep.depend() function inside it automatically updates.

Categories

Resources