Button within modal's table not firing [duplicate] - javascript

This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 3 years ago.
Attempted to put a delete button that works in a table into a modal, with a table and it's like the click event is not firing at all. Hit's not back end code, no console.log(s), or js break points. Am I missing something?
Modal's Table
<table class="table table-hover table-md ">
<thead>
<tr>
<td class="text-left TableHead">Role</td>
<td class="text-right TableHead">Delete</td>
</tr>
</thead>
#*--Table Body For Each to pull DB records--*#
<tbody>
#foreach (var role in Model.Roles)
{
<tr>
<td>#role</td>
<td>
<button class="sqButton btnRed float-right zIndex"
title="Delete" data-toggle="ajax-modal" data-target="#deleteRoleUser"
data-url="#Url.Action("Delete", "Administration",
new {Id = Model.Id , Type = "roleUser"})" >
<i class="glyphicon glyphicon-remove"></i>
</button>
</td>
</tr>
}
</tbody>
</table>
Controller that it's supposed to call
[HttpGet]
public async Task<IActionResult> Delete(string id, string type)
{
if (type == "user") {
ViewBag.Type = "user";
var user = await userManager.FindByIdAsync(id);
if (user == null)
{
ViewBag.ErrorMessage = $"User with Id = {id} cannot be found";
return View("NotFound");
}
var model = new EditUserViewModel
{
Id = user.Id,
UserName = user.UserName,
};
ViewBag.UN = user.UserName;
return PartialView("~/Views/Modals/_DeleteModalPartial.cshtml", model);
}
if (type == "roleUser")
{
ViewBag.Type = "roleUser";
var role = await roleManager.FindByIdAsync(id);
if (role == null)
{
ViewBag.ErrorMessage = $"Role with Id = {id} cannot be found";
return View("NotFound");
}
var model = new EditRoleViewModel
{
Id = role.Id,
RoleName = role.Name,
};
ViewBag.Role = role.Name;
return PartialView("~/Views/Modals/_DeleteModalPartial.cshtml", model);
}
else
{
ViewBag.ErrorMessage = $"cannot be found";
return View("NotFound");
}
}
I am not sure why the click event on the button is not working at all. I have tried removing random code and literally nothing is making it go over to the controller at the least.
EDIT added javascript
$(function () {
var placeholderElement = $('#modal-placeholder');
$('[data-toggle="ajax-modal"]').click(function (event) {
var url = $(this).data('url');
$.get(url).done(function (data) {
placeholderElement.html(data);
placeholderElement.find('.modal').modal('show');
});
});
});
$('.sqButton').click( function (event) {
event.stopPropagation();
});

Since the button doesn't exist on page load you will have to create a event delegate to something that does exist on page load that will attach the event to the right element when it finally does appear in the DOM
In this case we will use the document (because it always exists on page load, some people use 'body') to delegate the event to the [data-toggle="ajax-modal"], like this:
$(document).on('click', '[data-toggle="ajax-modal"]', function (event) {
// code here
});
This will attach the event to the [data-toggle="ajax-modal"] elements on page load AND after page load if the element gets added later.

Try replacing your javascript code
$('.sqButton').click( function (event) {
event.stopPropagation();
});
With the following code
$('.sqButton').click(function(event) {
var url = $(this).data('url');
$.get(url).done(function (data) {
placeholderElement.html(data);
placeholderElement.find('.modal').modal('show');
});
});

if you manually force click, does it hit your controller?
document.querySelector('.btnRed').click();
is there any other element(s) "hijacking" click event?

Related

how can i compare class to a string in js

I want to add toggle star functionality in my project. For which I'm calling this script on click. This code fails to compare value of starclass to the class defined in the string.
Here i m trying to add star/unstar functionality just like gmail messages to my project.
$(".mailbox-star").click(function (e) {
debugger;
e.preventDefault();
var $this = $(this).find("a > i");
var glyph = $this.hasClass("glyphicon");
var fa = $this.hasClass("fa");
var msgId = $("#MsgId").val();
var StarClass = $(".mailbox-star i").attr('class');
var StarStatus;
if (StarClass === "fa text-yellow fa-star-o") {
StarStatus = true;
} else {
StarStatus = false;
}
//var starstatus = document.getElementById('ReadstatusStarred');
if (glyph) {
$this.toggleClass("glyphicon-star");
$this.toggleClass("glyphicon-star-empty");
}
$.ajax({
url: "/Home/Starred",
type: "GET",
dataType: "json",
data: {
ChangeStarredStatus: StarStatus,
ChangeMessageId: msgId
},
success: function (status) {
if (status) {
alert(status);
if (fa) {
$this.toggleClass("fa-star");
$this.toggleClass("fa-star-o");
}
}
},
error: function () {
alert("starfailed1");
}
})
});
//HTML CODE
here i m fetching values from my controller using model .If I can send value of IsStarred parameter in my js code my problem will be sorted
<table class="table table-hover table-striped">
<tbody>
#{int count = 0;}
#foreach (var item in Model)
{
string[] dt = #item.DateTime.ToString().Split(' ');
<tr title="#item.DateTime" id="ReadMessage" class="#((item.IsRead != true) ? "row row-highlight" : "row")" >
<td><input type="hidden" value="#item.IsRead" id="Readstatus_#count"></td>
<td><input type="hidden" value="#item.IsStarred" id="ReadstatusStarred"></td>
<td><input type="hidden" id="MsgId" value="#item.MessageId" /></td>
<td><input type="checkbox"></td>
<td class="mailbox-star" ><i class="#((item.IsStarred==true)? "fa fa-star text-yellow":"fa text-yelow fa-star-o")"></i></td>
<td class="mailbox-name" id="Text1" onclick="location.href='#Url.Action("Read", "Home", new
{
NameRead = item.FullName,
SubjectRead = item.Subject,
BodyRead = item.Body,
DateRead = item.DateTime,
MessageIdRead= item.MessageId,
})'">
<a href="#" id="Name">
#item.FullName
</a>
</td>
<td class="mailbox-subject" id="Text1">
<b>#item.Subject</b>-
#if (item.Body == null || item.Body.Length == 0)
{
}
else
{
if (item.Body.Length >= 100)
{
#item.Body.Substring(0, 100)
}
else
{
#item.Body
}
}
</td>
<td class="mailbox-attachment"></td>
<td class="mailbox-date">
#dt[0]
</td>
</tr>
count++;
}
</tbody>
</table>
</div>
Try using jQuery's is() to check for classes instead
var StarStatus = $(".mailbox-star i").is('.fa, .text-yellow, .fa-star-o')
If I got your description right you wanna have something like gmail has, click to star a mail, click again to destar it?
It's hard to say what is broken without the HTML you are using but I would do this in the following manner:
When loading mails from back you have to set up class "starMarked" to starred mails depending on how you mark the starred mail in the data comming from back you would check if something is true or equal to some value and then .addClass("starMarked") to that element.
bind the .click(Function that does the logic below) to all elements that represent mail (list member, square, icon, depends on what you have in the UI)
A functionality of that click then checks if that mail is stared or not. Since the status is already represented with class no need to check through data pulled from the server or make an additional request to the server to get that email's status. This saves time and load on the server.
NOTE: You must be certain the request to change status on the server went through or your logic of toggling on front and status on backend might become inconsistent!
Toggle on front could be done numerous ways but simplest would be using the CSS class "starMarked" to represent it's starred and lack of it to signal it's not. It gives 2 birds with one stone (looks and logic). If you need to check the status you could use .hasClass("starMarked").
When toggling a class use .removeClass() to remove the class from the element

Razor and Ajax: How to reload a table upon successful Ajax call?

I have the following table that contains Razor code, it is a list of users along with each user's basic details, along with the option to edit or delete each user:
<table class="table table-striped">
<tr bgcolor="#FF0000"><th>Username</th><th>User Role</th><th>User Privileges</th><th>Status</th></tr>
#if (Model.Count() == 0)
{
<tr><td colspan="4" class="text-center">No User Accounts</td></tr>
}
else
{
foreach (AppUser user in Model)
{
if (!(user.UserName.ToLower().Equals("admin")))
{
<tr>
<td>#user.UserName</td>
<td>#user.UserRole()</td>
<td>#user.UserPrivs()</td>
<td>
#if (#user.LockedOut)
{
#:Locked
}
else
{
#: Unlocked
}
</td>
<td>
#using (Html.BeginForm("Delete", "Admin",
new { id = user.Id }, FormMethod.Post, new { #id = "manageusersform", name = user.UserName }))
{
<button class="btn btn-primary btn-xs editUserBtn"
data-id="#user.Id" name="#user.Id">
Edit
</button>
<button class="btn btn-danger btn-xs"
type="submit">
Delete
</button>
}
</td>
</tr>
}
}
}
</table>
<div style="text-align:center;">
<button class="btn btn-primary btn-xs" id="addnewuser">
Add New User
</button>
As shown above, there is also a button to add a new user. Clicking that brings up a popup form (with id signupform) to enter the new user's details, and when that form is submitted, the following javascript gets called:
$("form#signupform").submit(function (event) {
event.preventDefault();
var form = $(this);
$.post(form.attr("action"), form.serialize(), function (res) {
if (res.status === "success") {
alert(res.message);
$(".form-control").val('');
/*
reload the table
*/
}
else {
alert(res.message);
}
});
});
My goal is to implement the commented reload the table, without having to reload the entire page, which is what I am doing now:
$("form#signupform").submit(function (event) {
event.preventDefault();
var form = $(this);
$.post(form.attr("action"), form.serialize(), function (res) {
if (res.status === "success") {
alert(res.message);
$(".form-control").val('');
/*
$.ajax({
url: "/Admin/Index",
cache: false,
data: {}
}).done(function (htmlResponse) {
$("#tabs-1ua").html(htmlResponse);
});
*/
}
else {
alert(res.message);
}
});
});
Reloading the whole page causes some javascript issues such as the popup not working again, so I am trying to reload just the table now, and would like help.
Thank you.
You may create an action method which returns the partial view for the table markup.
public ActionResult GetUserTable()
{
var list = new List<AppUser>();
// to do : Populate list with data from your data source( user table?)
return PartialView(list);
}
and in the GetUserTable.cshtml partial view, put the view code you currently have to render the table
#{ Layout = null; }
#model List<AppUser>
<table id="usreList">
<!-- to do: loop throug model and render table rows) -->
</table>
You can use the same action method in your main view as well. Just call this action method
#Html.Action("GetUserTable","Users")
<div style="text-align:center;">
<button class="btn btn-primary btn-xs" id="addnewuser">
Add New User
</button>
This will render the user table same as what you currently have.
Now in your ajax success, you can reload your user table by calling this action method asynchronously.
if (res.status === "success") {
$("#usreList").load('/Users/GetUserTable');
}
Finally, for the jquery events you wired up to work with the newly injected/dynamic dom elements,you need to use on method.
So replace
$(".someClass").click(function(e){
// do something
});
with
$(document).on("click",".someClass",function(e){
// do something
});

How to filter data on screen with ajax using dropdown list? [duplicate]

In a MVC partial view file, I build one Html.TextBox and two submit buttons. These two buttons will increase/decrease the Html.TextBox value once clicked. The Html.TextBox displayed value will change accordingly.However, once I need to update the #refTable div based on the new value after click. The page or section never updated. Codes are below, where some comments are added for explanation purpose. Thanks for your help.
//******* cshtml file **********//
<body>
</body>
<input type="submit" value="PrevY" name="chgYr2" id="pY" />
#{
var tempItem3 = Model.First(); // just give the first entry from a database, works.
if (ViewData["curSel"] == null)
{
#Html.TextBox("yearSelect3", Convert.ToDateTime(tempItem3.Holiday_date).Year.ToString());
ViewBag.selYear = Convert.ToDateTime(tempItem3.Holiday_date).Year; // just initial value, works
ViewData["curSel"] = Convert.ToDateTime(tempItem3.Holiday_date).Year;
}
else
{
#Html.TextBox("yearSelect3", ViewData["curSel"].ToString());
}
}
<input type="submit" value="NextY" name="chgYr2" id="nY" />
<script type="text/javascript">
$(document).ready(function () {
$(document).on("click", "#nY", function () {
var val = $('#yearSelect3').val();
$('#yearSelect3').val((val * 1) + 1);
var dataToSend = {
id: ((val * 1) + 1)
}
// add some jquery or ajax codes to update the #refTable div
// also ViewBag.selYear need to be updated as ((val * 1) + 1)
// like: ViewBag.selYear = ((val * 1) + 1);
// any similar temp variable is fine
});
});
$(document).on("click", "#pY", function () {
var val = $('#yearSelect3').val();
$('#yearSelect3').val((val * 1) - 1);
var dataToSend = {
id: ((val * 1) - 1)
}
});
});
</script>
<span style="float: right">Set Holiday Calender for 2013</span>
<span id="btnAddHoliday">#Html.ActionLink("Add Holiday", "Create", null, new { id = "addHilBtn" })</span>
<div id="refTable">
<table class="tblHoliday" style="width: 100%;">
<th>
Holiday
</th>
<th>
Dates
</th>
<th>Modify</th>
<th>Delete</th>
</tr>
#foreach (var item in Model)
{
if ( Convert.ToDateTime(item.Holiday_date).Year == ViewBag.selYear)
// if the ViewBag.selYear is hard code, this selection "works"
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Holiday_Name)
</td>
<td>
#item.Holiday_date.Value.ToString("MM/dd/yyyy")
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { })
</td>
<td>
#Html.ActionLink("Delete", "Delete", new { })
</td>
</tr>
}
}
</table>
</div>
You'll need AJAX if you want to update a part of your page without reloading the entire page.
main cshtml view
<div id="refTable">
<!-- partial view content will be inserted here -->
</div>
#Html.TextBox("yearSelect3", Convert.ToDateTime(tempItem3.Holiday_date).Year.ToString());
<button id="pY">PrevY</button>
<script>
$(document).ready(function() {
$("#pY").on("click", function() {
var val = $('#yearSelect3').val();
$.ajax({
url: "/Holiday/Calendar",
type: "GET",
data: { year: ((val * 1) + 1) }
})
.done(function(partialViewResult) {
$("#refTable").html(partialViewResult);
});
});
});
</script>
You'll need to add the fields I have omitted. I've used a <button> instead of submit buttons because you don't have a form (I don't see one in your markup) and you just need them to trigger javascript on the client side.
The HolidayPartialView gets rendered into html and the jquery done callback inserts that html fragment into the refTable div.
HolidayController Update action
[HttpGet]
public ActionResult Calendar(int year)
{
var dates = new List<DateTime>() { /* values based on year */ };
HolidayViewModel model = new HolidayViewModel {
Dates = dates
};
return PartialView("HolidayPartialView", model);
}
This controller action takes the year parameter and returns a list of dates using a strongly-typed view model instead of the ViewBag.
view model
public class HolidayViewModel
{
IEnumerable<DateTime> Dates { get; set; }
}
HolidayPartialView.csthml
#model Your.Namespace.HolidayViewModel;
<table class="tblHoliday">
#foreach(var date in Model.Dates)
{
<tr><td>#date.ToString("MM/dd/yyyy")</td></tr>
}
</table>
This is the stuff that gets inserted into your div.
The main concept of partial view is returning the HTML code rather than going to the partial view it self.
[HttpGet]
public ActionResult Calendar(int year)
{
var dates = new List<DateTime>() { /* values based on year */ };
HolidayViewModel model = new HolidayViewModel {
Dates = dates
};
return PartialView("HolidayPartialView", model);
}
this action return the HTML code of the partial view ("HolidayPartialView").
To refresh partial view replace the existing item with the new filtered item using the jQuery below.
$.ajax({
url: "/Holiday/Calendar",
type: "GET",
data: { year: ((val * 1) + 1) }
})
.done(function(partialViewResult) {
$("#refTable").html(partialViewResult);
});
You can also use Url.Action for the path instead like so:
$.ajax({
url: "#Url.Action("Holiday", "Calendar", new { area = "", year= (val * 1) + 1 })",
type: "GET",
success: function (partialViewResult) {
$("#refTable").html(partialViewResult);
}
});

Update exiting element ng-repeat list in angularjs?

I made task table through the ng-repeat, Each task in table can can be modify. Task table will have to updated with updated task. So for this we need to access particular ng-repeat element. I want to know how to access particular ng-repeat element and update this with new task ng-click=editTask().
Please see $scope.editTask, Here I want to update inside $http.put(uri, data).
Workflow:
ng-click=beginTask(task) opens dialog, In dialog there is ng-click=editTask(), which will modify the task through $http.put...
Please see DEMO
<tr ng-repeat="task in tasks">
<td>{{task.title}}</td>
<td>{{task.description}}</td>
<td>
<a class="btn" data-toggle="modal" ng-click="beginEdit(task)">Edit</a>
</td>
</tr>
Angularjs code
$scope.beginEdit=function(task){
$scope.title = task.title;
$scope.description=task.description;
$scope.done=task.done;
$scope.uri=task.uri;
$scope.index=$scope.tasks.indexOf(task);
$('#edit').modal('show');
};
$scope.editTask = function() {
title=$scope.title;
description=$scope.description;
done=$scope.done;
uri=$scope.uri;
$('#edit').modal('hide');
var i=$scope.index;
var data={title: title, description: description, done: done };
$http.put(uri, data)
.success(function(){
alert("Success");
});
};
Please check this - : http://plnkr.co/edit/lVkWEsAGVLTY7mGfHP5N?p=preview
Add
$scope.tasks[$scope.index] = data;
In editTask
$scope.editTask = function(obj) {
alert($scope.title);
title = $scope.title;
description = $scope.description;
done = $scope.done;
uri = $scope.uri;
$('#edit').modal('hide');
var i = $scope.index;
var data = {
title: title,
description: description,
done: done
};
alert("uri" + uri);
alert(data.title);
$scope.tasks[$scope.index] = data; // For updating value
$http.put(uri, data)
.success(function() {
//tasks[i].uri(data.uri);
alert("Success");
});
};

HTML.Action Loop results in wrong model on page (variable scope pollution?)

I have a view (cshtml) that has a tab strip on it. The contents of each tab is of course different. The individual tabs have the correct data/information on them. There is some javascript that is intended to fire when a selection is made from the control on the individual tab. As it stands right now the first tab rendered the javascript fires. All other tabs do not fire. Further on the tab that does fire (first one) it obtains the correct value but then when trying to find the matching item in the model it doesn't find a match. Debugging shows that only the data for the last tab is available in the model. Well that explains why no match but begs the question of where did the data the first page was populated with go?
I have snipped the code for brevity. If, in my ignorance I left something out just say so and I'll post whatever is needed.
So to start here is the parent cshtml:
foreach (var extbrd in Model.ExternalBoards)
{
tabstrip.Add()
.Text(extbrd.ExtForumName)
.ImageUrl("~/.../ForumTabIcon.png")
.Content(#<text>
<div>
#Html.Action("ActionName", "Controller", new { id = extbrd.BoardId });
</div>
</text>);
}
Well as you can see above as we loop we call an action in the controller for each tab. Here is that action:
public ActionResult ActionName(int extforumid)
{
//get url for selected forum (tab) and pull feed
ExternalForums ExtFrm = _forumService.GetExternalForumById(extforumid);
reader.Url = ExtFrm.ForumUrl;
return View(reader.GetFeed());
}
That's actually it. As above I can post the reader code but I don't think it is the source of the trouble.
Well this action of course has a view and this is where I think things get wacky:
#model ExternalThreadsModel
<script type="text/javascript">
var model = #Html.Raw(Json.Encode(Model.RssThreads))
</script>
<script type="text/javascript">
$(function() {
$("##Html.FieldIdFor(model => model.ExtForumIds)").click(function () {
var selectedItem = $(this).val();
var matchingObj = getObjects(model, 'ThreadValue', selectedItem);
if(matchingObj > 0)
{
var $iframe = $('#ForumFrame');
if ( $iframe.length ) {
$iframe.attr('src', matchingObj[0].Link);
}
var $prevfram = $('#ForumPreview');
if ( $prevfram.length ) {
$prevfram.val(matchingObj[0].Description);
}
}
});
});
function getObjects(obj, key, val) {
var objects = [];
for (var i in obj) {
if (!obj.hasOwnProperty(i)) continue;
if (typeof obj[i] == 'object') {
objects = objects.concat(getObjects(obj[i], key, val));
} else if (i == key && obj[key] == val) {
objects.push(obj);
}
}
return objects;
}
</script>
<div>
<table>
<tr>
<td>
#Html.DropDownListFor(model => model.ExtForumIds, Model.SelectThreads, new {style = "...", #size = 30})
</td>
<td style="width:25px;"> </td>
<td>
#{ Html.Telerik().TabStrip()
.Name("ForumView")
.Items(tabstrip =>
{
tabstrip.Add()
.Text("Preview")
.Content(#<text>
<div>
<textarea style="background-color:#979797; text-decoration: none;" id="ForumPreview" name="ForumPreview" rows="26" cols="200" readonly></textarea>
</div>
</text>);
tabstrip.Add()
.Text("Interactive")
.Content(#<text>
<div>
<iframe id="ForumFrame" name="ForumFrame" src="" style="width:800px;height:350px;"></iframe>
</div>
</text>);
})
.SelectedIndex(0)
.Render();
}
</td>
</tr>
</table>
</div>
So as I mentioned each tab does have the correct data / information on it. The problem comes when a user selects an item from the drop down list.
The click handler only fires on the first tab. It doesn't fire for any other tabs???
Further on the first tab the click handler does fire and it pulls the correct selectedItem but when it runs through the helper function getobjects it doesn't find a match.
When I break and examine "model" as it is being passed into getObjects it only contains data for the last tab...so yeah nothing is going to be matched.
What is even stranger for me to understand is the line:
<script type="text/javascript">
var model = #Html.Raw(Json.Encode(Model.RssThreads))
</script>
In HTML it does render a json object with ALL the data from ALL the tabs...so...somewhere I must be running into variable scope pollution????
Your support and assistance is..as always..greatly appreciated.

Categories