How to disable and enable button in angular - html

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

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>

how to get all values of input number field which is generated in *ngfor

i have a table displaying cart products, in quantity field, i have a option for user to increase or decrease quantity,if i have update btn inside for loop, it is giving seperate btns for each, but i need single update btn outside for loop that gets all values of input field..
<tbody *ngFor="let cartproducts of cartpro.cartproducts ">
<input id="number" type="number" value="{{cartproducts.quantity}}" (change)="callMethod($event)" class="updatequan"> </tbody>
updatebtn:
<button type="button" class="btn btn-success" (click)="updatecart($event)">Update cart </button>
component.ts
callMethod(e:any)
{
this.quantity= e.target.value
console.log("current quantity",this.quantity)
}
updatecart(e:any){
console.log("udpate to",this.quantity)
}
if updatebtn is outside forloop, it is working , but it is showing the recently changed...but i need all changed stored in []
You need to look at ReactiveFormsModule
Basically you define a form and using .value property you can get any property you need
In your component file
constructor(private fb: FormBbuilder) { }
cartpro = this.fb.group({
cartProducts this.fb.array([
])
})
get cartProducts() {
return this.cartpro.get('cartProducts ') as FormArray
}
and in your html
<form [formGroup]='cartpro'>
<tbody formArrayName='cartProducts'>
<tr *ngFor="let cartproduct of cartProducts" [formGroupName]='i'>
<input id="number" type="number" formControlName='quantity' class="updatequan">
</tr>
</tbody>
</form>
Basically you now you can access the value of products with this.cartProducts.value

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 I can use the If coditIon for not showing some buttons to some users In Angular?

I have an array of blocked_users and now I don't want to show some buttons if a user is in Blocked_users.Here is my angualr.component.html
<div *ngIf="!(userId in event.blocked_users)">
<a class="btn btn-primary" (click)="onjoin(event.id)" >JOIN</a><br>
</div>
Here the if condition is not working.So can anyone please tell how to use the if condition if we don't want to show a button to some blocked_users.Any suggestions will be appreciated.
A computed property in the component class would do the trick I think.
#Component({
selector: 'my-app',
template:`
<button *ngIf="isUserAllowed">My Button</button>
`
})
export class AppComponent {
blockedUsers = [];
userId = 'someId';
get isUserAllowed():boolean{
return !this.blockedUsers.includes(this.userId);
}
}
It should be like:
<div *ngIf="!isBlockedUser(userId,event.blocked_users)">
<a class="btn btn-primary" (click)="onjoin(event.id)" >JOIN</a><br>
</div>
and in ts:
public isBlockedUser(currentUserId, blockedUserIds): boolean {
return blockedUserIds.find(id => id == currentUserId) != undefined;
}
You should *ngIf over an object , it should be something like,
<div *ngIf="!event.blocked_users">
<a class="btn btn-primary" (click)="onjoin(event.id)" >JOIN</a><br>
</div>
you can create a function in your component which will check if user exists in blocked_users like this
XYZ.component.html
*<div *ngIf="!isUserExists(userId)">
<a class="btn btn-primary" (click)="onjoin(event.id)" >JOIN</a><br>
</div>*
XYZ.component.ts
isUserExists(userId)() {
let result = this.blocked_users.filter(user => user.id == usersId);
if(result.length > 0) {
return true;
} else {
return false
}
}
You want to check if userId is anywhere in blocked_users.
You should have a function in your component that check if this is true or not instead of trying to do it in your template. Your template then needs to use the result of that function in the *ngIf:
Component
//Returns true if the user isn't in the blocked list, otherwise false
get isUserAllowed():boolean{
return !this.event.blocked_users.some(e=>e.id===this.userId);
}
You can also use includes instead of some here, but Stackblitz sometimes complains about includes and I like comparing just the id, so I used some
Template
<div *ngIf="isUserAllowed">
<a class="btn btn-primary" (click)="onjoin(event.id)" >JOIN</a><br>
</div>
Here's a Stackblitz to illustrate. Hope it helps :)

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

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