Change the color of button in particular tr of html table after submitting the form - html

Following code consists of html part.
I need to change the color of button of a particular row on click of it after all values in table body are validated
This code changes the color of button on click of it before validation.
<tbody>
<tr data-ng-repeat="val in finalData[0]" ">
<td><button type="button"
ng-click="storeTicketKey(val.TicketKey,val.clicked = !val.clicked)" class="btn btn-primary"
ng-class="{'btn-danger': !val.clicked, 'btn-success': val.clicked }"
data-toggle="modal" data-target="#myModal">{{val.TicketKey}}</button></td>
<td>{{val.Status}}</td>
<td>{{val.AssignedGroup}}</td>
<td>{{val.AssignedTo}}</td>
<td>{{val.L1}}</td>
<td>{{val.L2}}</td>
<td>{{val.L3}}</td>
<td>{{val.L4}}</td>
<td>{{val.L5}}</td>
<td>{{val.AssignedTo}}</td>
<td>{{val.ResponseSLAStatus}}</td>
<td>{{val.ResolutionSLAStatus}}</td>
<td>{{val.Region}}</td>
<td>{{val.SLABreachReason}}</td>
</tbody>

In the scenario you provided a solution would be removing the ng-class attribute and instead creating a (click)= "checkFields(event)" on the button and in your .ts you can create the function which will check the validity of the fields and change the class of your component.
Your .html:
<td><button type="button" ng-click="storeTicketKey(val.TicketKey,val.clicked = !val.clicked)" class="btn btn-primary" "checkFields(event)" data-toggle="modal" data-target="#myModal">{{val.TicketKey}}</button></td>
Your .ts:
checkFields(event: any){
//Check if the fields are valid, in this case I only check if they exist
if(!val.Status){
return;
}if(!val.AssignedGroup){
return;
}
.. and so on for all the fields you want to test
//If all variables are valid and the function gets to the end
//You change the class of the button
event.target.className = 'btn-success';
}

<tr data-ng-repeat="val in finalData[0] track by $index ">
<td><button type="button"
ng-click="storeTicketKey(val.TicketKey, $index)" class="btn btn-primary" ng-class="{'btn-success': $index=== isActive}"
data-toggle="modal" data-target="#myModal">{{val.TicketKey}}</button></td>
<td>{{val.Status}}</td>
<td>{{val.AssignedGroup}}</td>
<td>{{val.AssignedTo}}</td>
<td>{{val.L1}}</td>
<td>{{val.L2}}</td>
<td>{{val.L3}}</td>
<td>{{val.L4}}</td>
<td>{{val.L5}}</td>
<td>{{val.ResponseSLAStatus}}</td>
<td>{{val.ResolutionSLAStatus}}</td>
<td>{{val.Region}}</td>
<td>{{val.SLABreachReason}}</td>
</tbody>
$scope.valClicked=false;
$scope.isActive = "";
$scope.tempTicket="";
$scope.storeTicketKey = function(ticketKey,str) {
$scope.finalTicketKey=ticketKey;
$scope.tempTicket = str;
// $scope.valClicked=val;
}
$scope.isActiveButton = function(){
$scope.isActive = $scope.tempTicket;
}

Related

pass parameter to View Component after table row click

Inside a normal View, we are populating a table via the model with this:
#foreach (var item in Model)
{
if (item.PartnerSubscriptionID > 0)
{
<tr id='customlistid_#item.CustomList.ListID'>
<td>
<button type="button" class="btn btn-secondary" onclick='ListCustomEdit("#item.CustomList.ListID")'>
<i class='fas fa-users'></i>
</button>
</td>
<td style="display:none">#Html.DisplayFor(modelItem => item.CustomList.ListID)</td>
<td style="text-align:left">#Html.DisplayFor(modelItem => item.CustomList.ListName)</td>
<td><button id='btnDelete' type='button' class='btn btn-danger' onclick='ListCustomDeleteConfirm(" #item.CustomList.ListID ")'><i class='fas fa-trash'></i></button></td>
</tr>
}
}
On the same page I have a View Component. It works when I hard code the ListID like this:
<div class="col-8">
#await Component.InvokeAsync("ListCustomMembers" , new {ListID = 7 } )
</div>
But we need the ID to be passed in when the user clicks the row. Ie, where we currently have the onclick=ListCustomEdit() we need to refresh the View Component with the correct ID.
How do I do it?
ViewComponent is rendered on the server side, so when the user clicks in the browser, you need to send another request to the server to render and return the ViewComponent with the new parameter, for which you can use a controller.
Create an action in the controller you want to return the ViewComponent, then update the view as shown below after clicking the button using jquery
public class TestController : Controller
{
public IActionResult GetNewList(int listId)
{
return ViewComponent("ListCustomMembers", new { listId });
}
}
on the view side:
<button type="button" class="btn btn-secondary" onclick='ListCustomEdit("#item.CustomList.ListID")'>
<div class="col-8" id="ListCustomMembers">
#await Component.InvokeAsync("ListCustomMembers" , new {ListID = 7 } )
</div>
<script>
function ListCustomEdit(listId) {
$.get('/test/GetNewList/?listId=' + listId,
function(result) {
$("#ListCustomMembers").html(result);
});
}
</script>

Function change text does not work if I add font awesome

This is my function that takes the id from my button and changes the text:
var modal_button_update = document.getElementById("modal_button_text");
if (modal_button_update.innerHTML === "Add") { modal_button_update.innerHTML = "Update"; }
It's working fine with this button (Add becomes Update)
<button type="button" class="btn btn-primary save_button add_group" id="modal_button_text">Add</button>
But for some reason it does not change anymore if I try to add a font awesome icon:
<button type="button" class="btn btn-primary save_button add_group" id="modal_button_text"><i class="fas fa-save" aria-hidden="true"></i>Add</button>
What could be the cause?
I ran your code. It seems the problem is that you are checking if your modal_button_update button's innerHTML is equal to Add. The original button:
<button type="button" class="btn btn-primary save_button add_group" id="modal_button_text">Add</button>
works because the innerHTML of your modal_button_update is exactly 'Add', but your modified modal_button_update: <button type="button" class="btn btn-primary save_button add_group" id="modal_button_text"><i class="fas fa-save" aria-hidden="true"></i>Add</button> does not work because the innerHTML is <i class="fas fa-save" aria-hidden="true"></i>>Add which is not equal (===) to 'Add'.
Here's three different ways I chose to solve this issue:
Remove the <i class="fas fa-save" aria-hidden="true"> element and place the font-awesome icon inside the button class like: <button type="button" class="btn btn-primary save_button add_group fas fa-save" id="modal_button_text">Add</button>
`
Alter your Javascript to look something like: var modal_button_update = document.getElementById("modal_button_text"); if (modal_button_update.innerHTML.includes("Add")) { modal_button_update.innerHTML = "Update"; }
Here the button checks to see if the innerHTML contains 'Add'.
Keeping the font-awesome icon:
In the two solutions above, your Javascript code will strip the button element of the font-awesome class when successfully changing the innerHTML to 'Update'. It is, imo, easier to use jQuery to alter the value of the button to solve this issue like:
---HTML---
<button type="button" class="btn btn-primary save_button add_group" id="modal_button_text"><i class="fas fa-save" aria-hidden="true"></i>Add</button>
---Javascript--
if ($('#modal_button_text').html().includes("Add")) {
$('#modal_button_text').html("Update");
}
If your intent is to keep the icon no matter the state of the text (i.e., Add or Update), I would personally enclose the word "Add" in a span as follows:
HTML:
<button type="button" class="btn btn-primary save_button add_group" id="modal_button_text"><i class="fas fa-save" aria-hidden="true"></i><span id="modal_button_span">Add</span></button>
Then it is just a matter of whether you use jQuery or not as to which of the following will work for you.
JavaScript:
Change value based on current text:
if(document.getElementById("modal_button_span").innerHTML === "Add") document.getElementById("modal_button_span").innerHTML = "Update";
Toggle value when the button is clicked based on current text:
document.getElementById("modal_button_span").innerHTML = document.getElementById("modal_button_span").innerHTML === "Add" ? "Update" : "Add";
jQuery:
Change value based on current text:
if($("#modal_button_span").html() === "Add") $("#modal_button_span").html("Update");
Toggle value when the button is clicked based on current text:
$("#modal_button_span").html($("#modal_button_span").html() === "Add" ? "Update" : "Add");
By enclosing the word Add in a span, you are free to do whatever you need to the text without disrupting the rest of the button or save icon.

How disable last <td> from clicking?

I want to disable last from clicking because that column contains the delete action button.
I do not want to use JS or JQuery, I was wondering if it is posible to disable it inside HTML tag code.
This is not a duplicated question because most similar questions include the use of JS or Jquery which I don't want to use.
<tr onclick="location.href = '#Url.Action("DetallePedido", "Pedidos", new { id = pedido.Id })'" class="bg-warning">
<td>#pedido.Id</td>
<td>#pedido.FechaPedido</td>
<td>#pedido.Cliente.Nombres</td>
<td>#pedido.Region</td>
<td>#pedido.ContactoPrincipal</td>
<td>#pedido.Telefonoc</td>
<td>#pedido.SubTotal</td>
<td>#pedido.Total</td>
<td>#pedido.FechaEntrega</td>
<td>#pedido.Direccion</td>
<td>
#if (pedido.User != null)
{
#pedido.User.Name
} else
{
#pedido.Vendedor
}
</td>
<td class="text-center"><a class="btn btn-danger btn-xs text-white" onclick="cancelarPedido(#pedido.Id)"><i class="fas fa-trash-alt"></i></a></td>
</tr>
You could set CSS style="pointer-events: none;" to the delete link. See: https://css-tricks.com/almanac/properties/p/pointer-events/
It's not very nice solution though, you'd better just change the onclick attribute to return: false;.

how can i use this modal within my foreach loop? (HTML / Razor)

I have a button that when clicked should open a modal with a confirmation stating whether the user would like to delete the selected line or not, hence on the modal, there is a 'Yes' and 'No' option. With the 'Yes' button carrying out the onclick function which is responsible for deleting the line item (These operations take place within my controller and are not part of this question). To provide a bit of background, originally the onclick function had been part of my button, which now opens the modal, and this worked perfectly as intended. However, now that button serves only one purpose, and that is to open the modal. Within the modal, the onclick function has now been moved to the 'Yes' button. But now, this onclick function does not work as it use to, and i believe this is something to do with the foreach loop that all of this is in.
Below is the code for the button and modal:
#Model.CategoryList.result
#if (Model.CategoryList.result == "")
{
int count = 0;
foreach (String dataLine in Model.CategoryList.userData)
{
string countString = count.ToString();
string target = "dataLine" + countString;
string trigger = "#" + target;
string deleteHolder = dataLine.Split(Model.CategoryList.delimiterChar)[0];
<p>
<a data-toggle="collapse" href="#trigger" role="button" aria-expanded="false" aria-controls="collapseExample">
#dataLine.Split(Model.CategoryList.delimiterChar)[0]
</a>
<button class="btn" data-toggle="modal" data-target="#deleteHolder" id="#dataLine.Split(Model.CategoryList.delimiterChar)[1]"></button>
</p>
<div class="modal" id="deleteHolder" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>Modal body text goes here.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" onclick="location.href = '#Url.Action("DeleteCategoryLine", "Index", new { id = dataLine.Split(Model.CategoryList.delimiterChar)[1] })'">Yes</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">No</button>
</div>
</div>
</div>
</div>
count++;
}
}
The problem i have is: The onclick event deletes a line in the text file, that is why i have count, trigger and target to identify WHICH line to delete. However, after moving the onclick event to my modal, it will always delete the first line in the text file. I am unsure as to why this happens? Do i not understand the implications a modal presents?
My controller Action:
public ActionResult DeleteCategoryLine(int id, string changedItem)
{
string strFilePath = "~/App_Data/Category.txt";
string strSearchText = id.ToString();
string strOldText;
string n = changedItem;
StreamReader sr = System.IO.File.OpenText(Server.MapPath(strFilePath));
while ((strOldText = sr.ReadLine()) != null)
{
string[] x = strOldText.Split(',');
if (!x[1].Contains(strSearchText))
{
n += strOldText + Environment.NewLine;
}
}
sr.Close();
System.IO.File.WriteAllText(Server.MapPath(strFilePath), n);
}
As per our chat, the answer to this issue was that the ID of the modal was not unique and so it was creating the first and that's that.
I advised OP to suffix the modal with a unique ID
deleteHolder_#dataLine.Split(Model.CategoryList.delimiterChar)[1]
and it seems to have worked.

How to disable and enable button in angular

I have an array of objects with delete button hidden when page loads. Now I want to show the delete button when new object is pushed to the array, the existing objects button should still remain hidden. How do I hide existing buttons and only show new object delete button.
html
<div>
<table >
<tr>//.....</tr>
<tr *ngFor="list of Array1">
<td><button type="button" class="btn btn-danger"
(click)=remove(i) [disabled]="disabled">
<i class="glyphicon glyphicon-remove"></i>
</button></td>
<td>{{list.type}}</td>
<td>{{list.year}}</td>
</tr>
</table>
</div>
<div>
<table >
<tr>//.....</tr>
<tr *ngFor="list of Array2">
<td><button type="button" class="btn btn-secondary"
(click)=addObj(i)>
<i class="glyphicon glyphicon-plus"></i>
</button></td>
<td>{{list.type}}</td>
<td>{{list.year}}</td>
</tr>
</table>
</div>
Here is the code used for adding new object from another array:
ts
//..
disabled = false;
....
addObj(index) {
// is there a way I can enable the delete button of just the index pushed?
this.Array1.push(this.List[index]);
this.List.splice(index, 1)
}
Define a variable to show/hide the button
isDisabled = true;
Then change the variable state in your code where you are pushing new items to the array. It could be any method or inside subscriber etc.
this.isDisabled = false; // or this.isDisabled = !this.isDisabled;
then in your button bind disabled attribute with this isDisabled variable.
[disabled]="isDisabled"
Complete Button Example
<button (click)="delete(item.id)" [disabled]="isDisabled">Delete</button>
try this
<button type="button" class="btn btn-danger"
(click)=remove(i) [disabled]="!show">
<i class="glyphicon glyphicon-remove"></i>button
</button>
//..
show = false;
....
addObj(index) {
// is there a way I can enable the delete button of just the index pushed?
this.Array1.push(this.List[index]);
this.show = true;
this.List.splice(index, 1)
}
Create a dummy array containing the index of newly added object. And then make condition on that array in *ngIf.
Html
<button type="button" class="btn btn-danger"
(click)=remove(i) *ngIf="deleteButtonShowIndex.indexOf(i) !== -1">
<i class="glyphicon glyphicon-remove"></i>
</button>
Component
deleteButtonShowIndex = [];
addObj(index) {
deleteButtonShowIndex.push(index);
this.Array1.push(this.List[index]);
this.List.splice(index, 1)
}
The better approach I will suggest is to maintain a flag in this.Array1 as shown below:
this.Array1 = [{
show: false,
data: {}
},
{
show: false,
data: {}
},
{
show: true,
data: {}
}
];
Declare a property showButton which will be used to decide whether button will be displayed or not. And when you insert a new record make this showButton property to true which will lead to show the button like shown in the demo. Then in your template you can easily use *ngIf to decide whether to show the button or not.
app.component.html
<button (click)="addButtonHandler()">
add record
</button>
<table >
<tr>
<th>Name</th>
<th>Action</th>
</tr>
<tr *ngFor = "let val of item">
<td>{{val.name}}</td>
<td *ngIf="val.showButton"><button>click me</button></td>
</tr>
</table>
app.component.ts
name = 'Angular';
item:Item[]=[]
constructor(){
this.item.push({
'name':'Monica',
'showButton':false
})
this.item.push({
'name':'Rachel',
'showButton':false
})
}
addButtonHandler(){
this.item.push({
'name':'phoebe',
'showButton':true
})
}
Working demo: link