How to add disabled attribute to button in react? - html

Here is my code
import React from 'react'
import PropTypes from "prop-types";
export default function Button({ htmlType, type, disabled, action, ...props}) {
return (
<button type={htmlType} onClick={action}>
{props.children}
</button>
)
}
Button.propTypes = {
htmlType: PropTypes.string.isRequired,
action: PropTypes.func,
disabled: PropTypes.bool
};
I call Button component by this code
<Button disabled={true}>button title</Button>
I want to add disabled html attribute to button when disabled of props is true, how to do it ?

You could line single line if-else statements like this:
<button disabled={propsDisabled}>button title</button>
Here, propsDisabled is the variable which you can pass through the props, and it is a boolean variable which will either be true or false. I have not used disabled itself to avoid confusion but you can use the variable name as disabled.
When propsDisabled is true, the button will be dissabled, and when propsDisabled is false the button will not be disabled.

Aya, I couldn't exactly understand your question, it looks like you're trying to solve a problem, when you have a second problem in the question in the first place.
Are you using Ant components? use the disabled prop on the <Button /> component itself. (notice the capital B in the component name Button).
<Button disabled={true} />
// or (it's the same but different JSX syntax)
<Button disabled />
This is the same answer answered by the brother #Abdul Qadir.
If you're working with native HTML elements, also, you can call the disabled attribute on the <button /> element (notice the small character b in the element name button) the same way and it should work:
<button disabled={true}>I'm disabled</button>
// or (the same but different syntax)
<button disabled>I'm disabled</button>
So here are the two answers,
If you're working with Ant components:
import { Button } from 'antd';
const CustomButton = ({ disabled, children }) =>{
return <Button disabled={disabled}>{children}</Button>
}
If you're working with native HTML elements:
const CustomButton = ({ disabled, children }) =>{
return <button disabled={disabled}>{children}</button>
}

Related

Pass the text to be displayed on button as a paramter

I written a html code which calls, an uploader component.
<app-uploader [Details]="Details" (onSubmit)="onSubmitEvent($event)"> </app-uploader>
Now the app-uploader component has a line something like:
<button mat-button
[disabled]="(canSubmit$ | async) === false"
color="primary"
i18n="button text, submit file for uploading"
(click)="submitUpload()">
Submit
</button>
However, I don't want the text Submit to appear for my particular use-case.The app-uploader component is a global component and hence I could not change the text directly there. Is there any way to pass any argument when I call the component from my html file such that the word Submit gets overridden while deploying my project?
Based on your comment and the post, to me it seems that this button should be showing a different text depending on the use case.
I suggest to define an input field in the UploaderComponent and then display that as the text of the button.
uploader.component.ts:
#Component({
selector: 'app-uploader',
templateUrl: './uploader.component.html',
styleUrls: ['./uploader.component.scss']
})
export class UploaderComponent {
#Input() buttonText: string = 'Submit'; // default value is submit
// ...
constructor() {}
// ...
}
uploader.component.html:
<button mat-button
[disabled]="(canSubmit$ | async) === false"
color="primary"
i18n="button text, submit file for uploading"
(click)="submitUpload()">
{{buttonText}}
</button>
Now you use the component as follows ([buttonText]="Your favorite text"):
<app-uploader [buttonText]="Your favorite text" [Details]="Details" (onSubmit)="onSubmitEvent($event)"> </app-uploader>

Changing values of a counter variable in Angular

I have 2 buttons on my login page, Button1 and Button2. Both the buttons direct to the same URL page. But on clicking Button 2, I want to disable the functionality of Button 3 which is on the next URL page.
Button 3 should be accessed only when Button 1 was clicked on the main page.
Here's the HTML code of the main page. Button 1 is a part of the ngForm.
<button class="btn btn-primary" id="alert" type="submit">Login</button>
<button class="btn-primary" routerLink="/login/olduser" id="logins">Patient Login</button>
Here's the HTML code of Second page.
<button class="btn btn-primary" style ='margin-left: 700px;'routerLink="../../login/newuser">Register a new patient </button>
One possible solution I thought of was exporting a counter variable from the main page to the second page on clicking Button 2, which will inform to disable Button 3, but I failed to do so.
How can I implement this functionality?
Here's what I have tried till now :
<button class="btn-primary" (Click)="newUser()" id="logins">Patient Login</button>
public newUser(){
var status="success";
console.log(status);
this.router.navigateByUrl('/login/olduser');
}
I'm trying to print the value of "status" on console, to check if the method is being accessed but there's no output on console and also the url doesn't change.
I want to call this "status" variable in olduser.ts script.
It seems you're trying to limit the functionality of some sort of dashboard depending on user type (patient, non-patient).
I don't think you should rely on a referrer button at all here.
I'd send something like a list of permissions for user to client app after logging in and wrap it in a AuthorizationService of some kind. Then I'd check if the user has the permission to register a new patient and show/hide the corresponding button.
Of course, you shouldn't forget about server-side validation for registration requests.
UPD: if one of the user types doesn't distinguish between users and doesn't require server-side authentication, you can just generate some kind of default set of permissions in the service for those non-privileged users and keep the display logic for page 2 based on permission checks.
On Click of button pass a query parameter. Then on the next page read the value of the query parameter from URL and disable the button 3 based on the value.
Working Demo
Homepage HTML
<a routerLink='/page1' [queryParams]="{button: 'a'}"><button>button 1</button></a>
<a routerLink='/page1' [queryParams]="{button: 'b'}"><button>button 2 </button></a>
<router-outlet></router-outlet>
In the routed component .TS
import { Component, Input, OnInit } from "#angular/core";
import { ActivatedRoute } from "#angular/router";
#Component({
selector: "hello",
template: `
<h1>Hello {{ name }}!</h1>
<button [disabled]="isDisable">button3</button>
`,
styles: [
`
h1 {
font-family: Lato;
}
`
]
})
export class HelloComponent implements OnInit {
#Input() name: string;
isDisable: boolean;
constructor(private activatedRoute: ActivatedRoute) {}
ngOnInit() {
this.activatedRoute.queryParams.subscribe(params => {
this.isDisable = params.button === "a";
});
}
}
You can send the state of the button as a query parameter on button 2 click. Now, On the new page get the query params value and then apply property binding.
On Button 2 click :
this.router.navigate(['/newpage'], { queryParams: { state: "false"});
Now, on new page add as below :
import { ActivatedRoute } from '#angular/router'
export class newPage implements OnInit {
btnState
constructor(private route: ActivatedRoute) { }
ngOnInit() {
this.route.queryParams
.filter(params => params.state)
.subscribe(params => {
this.btnState = params
});
}
Now,apply property binding to the button
<button [disabled]="btnState">Button3</button>
There is multiple ways to achieve what you try to do:
With the click on Button 2, you can store in a service, a variable isActive to false and in your next url/Component, check from the service the variable to disabled or not your Button 3.
Navigate to your url with a params: my-new-url?ACTIVE=false, and in your new url/component, check the url to find the Params and disable your button according to the value

How to refresh/reload a parent component onclick of child component submit button in angular 6?

My parent component ts file contains this code:
openNewModal(): void {
this.$modal.show(CategoryAddModalComponent)
.subscribe(r => {
});
location.reload();
}
My child component html:
<form action="">
<label>Enter Category</label>
<input name="cate" type="text">
<input name="category" type="text">
<button class="common-btn btn-cancel" (click)="modal.hide();l>Cancel</button>
<button class="common-btn btn" type="submit" (click)="fun_addcategory()">Submit</button>
</form>
So using this openNewModal() function Im calling my child component model. Now On submit of my child component I need to reload my parent component file. If I try to call location.reload in this function, my child component is getting reloaded. But I need to reload parent component. Can somebody please guide me how to do this?
No need to Reload the page
Use ChangeDetectorRef to detect changes manually inside parent
Example:
parent.ts
import {ChangeDetectorRef} from '#angular.core';
constructor(private cdr:ChangeDetectorRef){}
ngOnInit(){
this.service.susbscribe((data)=>{
this.data=data;
//detect the change manually using
this.cdr.detectChanges();
//Checks this view and its children.
local change detection checks
})}
You need to pass an addition flag to skip location changes like this
'''
this.router.navigate(['parentComponent', id, type], {skipLocationChange: true});
'''

How can I change component without changing URL in Angular?

I would like to change component without changing URL. Let's assume that I have a component register. When I open my website I have url www.myweb.com. Then I would like to register by clicking sign up. I would like to display my component register without changing URL. Should I use ngIf or something else? Can you show me example how it should be done?
UPDATE I am sorry, but it seems to me that I was misunderstood. I tried
this solution:
login.component.ts:
showSignUp: boolean = false;
login.component.html:
<button (click)="showSignUp = true">Sign Up</button>
<register *ngIf="showSignUp"></register>
However when I clicking the button Log in I get this:
before:
after clicking:
After clicking the button Log in I would like to get a new website but with the same URL like this:
UPDATE
What do you think about solution shown below? In html file I will be checking whether variable authenticated is equal true. If so then I will display home component.
login() {
this.loading = true;
this.authenticationService.login(this.model.username, this.model.password)
.subscribe(
data => {
this.authenticated = true;
// this.router.navigate([this.returnUrl]);
},
error => {
this.authenticated = false;
this.alertService.error(error);
this.loading = false;
});
}
UPDATE
Unfortunately it doesn't work. Any ideas how can I use it with this button?
<button [disabled]="loading" class="btn btn-primary">Log in</button>
You can use *ngIf and show the component in condition!
examle
In your sign up component, set a variable and change its value on click of sign up button. And display your register component on click of the login by pitting the condition in display
// sign up component
showRegister = false;
in your sign up component html
<register *ngIf="showRegister"></register>
Yes, this is a perfect use case for ngIf. Try not to over engineer it.
ngIf is the way to go on this kind of thing.
Just put in your component code something like
showSignUp: boolean = false;
then in template:
<button (click)="showSignUp = true">Sign Up</button>
<register *ngIf="showSignUp"></register>
And since you seem new to Angular, I'll mention that in order to use ngIf in template, your module needs to import the CommonModule like
import { CommonModule } from '#angular/common';
imports: [
CommonModule,
]

Performing Click on an ElementRef object in Angular 4 [duplicate]

I am trying to fire click event (or any other event) on element programatically , In other word I want to know the similar features as offered by jQuery .trigger() method in angular2.
Is there any built in method to do this? ..... if not please suggest how can i do this
Consider the following code fragment
<form [ngFormModel]="imgUploadFrm"
(ngSubmit)="onSubmit(imgUploadFrm)">
<br>
<div class="input-field">
<input type="file" id="imgFile" (click)="onChange($event)" >
</div>
<button id="btnAdd" type="submit" (click)="showImageBrowseDlg()" )>Add Picture</button>
</form>
Here when user click the btnAdd it should fire the click event on imgFile
Angular4
Instead of
this.renderer.invokeElementMethod(
this.fileInput.nativeElement, 'dispatchEvent', [event]);
use
this.fileInput.nativeElement.dispatchEvent(event);
because invokeElementMethod won't be part of the renderer anymore.
Angular2
Use ViewChild with a template variable to get a reference to the file input, then use the Renderer to invoke dispatchEvent to fire the event:
import { Component, Renderer, ElementRef, ViewChild } from '#angular/core';
#Component({
...
template: `
...
<input #fileInput type="file" id="imgFile" (click)="onChange($event)" >
...`
})
class MyComponent {
#ViewChild('fileInput') fileInput:ElementRef;
constructor(private renderer:Renderer) {}
showImageBrowseDlg() {
// from http://stackoverflow.com/a/32010791/217408
let event = new MouseEvent('click', {bubbles: true});
this.renderer.invokeElementMethod(
this.fileInput.nativeElement, 'dispatchEvent', [event]);
}
}
Update
Since direct DOM access isn't discouraged anymore by the Angular team this simpler code can be used as well
this.fileInput.nativeElement.click()
See also https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent
I also wanted similar functionality where I have a File Input Control with display:none and a Button control where I wanted to trigger click event of File Input Control when I click on the button, below is the code to do so
<input type="button" (click)="fileInput.click()" class="btn btn-primary" value="Add From File">
<input type="file" style="display:none;" #fileInput/>
as simple as that and it's working flawlessly...
This worked for me:
<button #loginButton ...
and inside the controller:
#ViewChild('loginButton') loginButton;
...
this.loginButton.getNativeElement().click();
To get the native reference to something like an ion-input, ry using this
#ViewChild('fileInput', { read: ElementRef }) fileInput: ElementRef;
and then
this.fileInput.nativeElement.querySelector('input').click()
Günter Zöchbauer's answer is the right one. Just consider adding the following line:
showImageBrowseDlg() {
// from http://stackoverflow.com/a/32010791/217408
let event = new MouseEvent('click', {bubbles: true});
event.stopPropagation();
this.renderer.invokeElementMethod(
this.fileInput.nativeElement, 'dispatchEvent', [event]);
}
In my case I would get a "caught RangeError: Maximum call stack size exceeded" error if not. (I have a div card firing on click and the input file inside)
If you want to imitate click on the DOM element like this:
<a (click)="showLogin($event)">login</a>
and have something like this on the page:
<li ngbDropdown>
<a ngbDropdownToggle id="login-menu">
...
</a>
</li>
your function in component.ts should be like this:
showLogin(event) {
event.stopPropagation();
document.getElementById('login-menu').click();
}