How can I change component without changing URL in Angular? - html

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,
]

Related

How to add disabled attribute to button in react?

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

Angular: Enable button asynchronously

I am fetching data in my angular app from a REST API. I want to enable the button of the search once the user logs in. I have added auth.service.ts which I am importing in my search navbar component. But, the button doesn't get enabled once the user logs in. The data is asynchronous so, it either remains disabled or enabled. I can't figure it out.
Here's my code:
navbar.component.ts
allowSearch: boolean = false;
buttonEnable() // this should get called every time change is detected in the input
{
if(this.authService.isAuthenticated())
{
this.allowSearch = true;
}
}
navbar.component.html
<input type="text" value="" class="form-control" (change) = "buttonEnable()" placeholder="Search..." [(ngModel)] =
"searchElement" name = "searchElement"
style = "background-color: #faf9f9" id = "searchElement" >
<div class="input-group-append" style = "background-color: #faf9f9">
<button type="button" name="button" type = "submit" [disabled] = "!allowSearch" (click) =
"openModal2(); onSearch(searchElement)"><i class="nc-icon nc-zoom-split"></i></button>
</div>
If you call to authService outside of navBar, you can get it if your service has, futhermore a method to login, a Subject. Else simply change the variable in the subscribe function.
e.g. using Subject:
LoginService(){
isLoggin:Subject<boolean>=new Subject<boolean>()
loggin(data){
this.httpClient.get(....).pipe(
tap(res=>{
if (.....)
this.isLoggin.next(true)
})
)
}
loggout(){
this.httpClient.get(....).pipe(
tap(_=>{
this.isLoggin.next(false)
})
)
}
}
Your nav-bar-component inject in constructor the loginService -make it public-
constructor(public loginService:LoginService){}
And your .html can be simple
<button [disabled]="!(loginService.isLoggin|async)">I'm login</button>
(*)tap not change the response, but executed when "someone" subscribe to our observable.
Here 'this.allowSearch' is getting initialized in buttonEnable(). Once you login to the application, You should call the 'buttonEnable()' method.
Same wise, When ever you logout from app, you should invoke the 'buttonEnable()' method.
So 'allowSearch' value will be updated.
Instead of this approach, you should have RXJS observables. have 'allowSearch' property in RXJS store and update based on login and logout actions.
Your component should subscribe for 'allowSearch' from store and update the 'allowSearch' component property.

Get selected tab to switch icons Ionic 5

I'm trying to change my tab icons from filled to outline when someone selects it (filled when selected, outline when not selected).
On the Ionic 5 Tabs Doc there's a getSelected() method but no examples on how to use this.
My idea was to use ionTabsDidChange to detect when someone clicked a tab, then use getSelected() and set the icon from 'home' to 'home-outline'.
Tabs.html
<ion-tabs>
<ion-tab-bar slot="bottom">
<ion-tab-button class="tab-btn" tab="home">
<ion-icon name="{{ homeIcon }}"></ion-icon>
<ion-label>Home</ion-label>
</ion-tab-button>
<ion-tab-button class="tab-btn" tab="price">
<ion-icon name="{{ priceIcon }}"></ion-icon>
<ion-label>Price Search</ion-label>
</ion-tab-button>
<ion-tabs>
Tabs.ts
export class TabsPage {
public homeIcon = 'home';
private homeFilled = 'home';
private homeOutline = 'home-outline'
public priceIcon = 'search-outline';
private priceFilled = 'search';
private priceOutline = 'search-outline';
ionTabsDidChange() {
let selectedTabName = getSelected();
// Stuff to switch icon from filled to outline and vice versa
}
}
The issue is that I don't know how to use getSelected(), I've tried adding ViewChild like this stackoverflow, but getSelected() is not a function (Changed to IonTabs because Tabs don't exist in Ionic 5.
At this point, the only solution I can think of is saving the tabs state and adding click functions for everything.
You are heading the right direction, there are still few missing points. In the Ionic doc you are reading the "events" are not directly accessible in the page without binding them to the component itself and in order to use ViewChild you also need to give the component an id:
Tabs.html
<ion-tabs #tabs (ionTabsDidChange)="setCurrentTab()">
"tabs" will be the id of the component and whenever ionTabsDidChange event gets triggered it will call setCurrentTab method, it should be declared on your page.
Then in the page, as you have already mentioned you'll need to add a ViewChild (now possible with the id) and use getSelected() method.
Tabs.ts
export class TabsPage {
#ViewChild('tabs', { static: false }) tabs: IonTabs;
...
setCurrentTab() {
this.selectedTab = this.tabs.getSelected();
}
}
And voila, that should be it :-)
There's another really easy way to do this. First add the ionTabsDidChange attribute to your ion-tabs element as #andriyleu suggests but this time make sure to pass $event details in.
<ion-tabs (ionTabsDidChange)="setCurrentTab($event)">
Then you can define the function in your ts file like this.
current_tab = "home"; // Set this as you default page name
setCurrentTab(ev: any){
this.current_tab = ev.tab;
}
Finally, in your html you can use a very efficient piece of Javascript to determine which icon to show. Perhaps like me, you're switching between a filled and outline version.
<ion-icon [name]="current_tab == 'home' ? 'home' : 'home-outline'"></ion-icon>
Thanks to the everyone who answered this and helped me figure it out!
Inside the ion-tabs tag, ionTabsDidChange passes an event which has the selected tab. You can get that event by doing the following then it should give you the clicked tab:
tabs.html
<ion-tabs (ionTabsDidChange)="tabClicked($event)">
tabs.ts
tabClicked(e) {
this.selectedTab = e.tab
}
Doesn't work in React.
const log = (e: any): any => {
console.log(e);
}
<IonTabs ionTabsDidChange={log}>
Type '{ children: Element[]; ionTabsDidChange: (e: any) => any; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<IonTabs> & Readonly<Props> & Readonly<{ children?: ReactNode; }>'.
[react-scripts] Property 'ionTabsDidChange' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<IonTabs> & Readonly<Props> & Readonly<{ children?: ReactNode; }>'. TS2322
[react-scripts] 47 | <IonApp>
Any thoughts?
Ionic will add "tab-selected" class to the selected tab. You can use that class to style the tab icon.
This post is old and answered but I'm going to expand Shrishail's answer, because I think it's the better answer and it didn't get enough attention. when you just want to change looks, like changing icon, it's better to use css. here is a working example based on tab-selected class:
<ion-tab-button>
<ion-icon name="home" class="selected"></ion-icon>
<ion-icon name="home-outline" class="unselected"></ion-icon>
<ion-label>Home</ion-label>
</ion-tab-button>
and in css:
.tab-selected .unselected {
display: none;
}
.tab-selected .selected {
display: initial !important;
}
.selected {
display: none;
}
For people that use react.js, this solution was effective for me.
const App: React.FC = () => {
const [selectedTab, setSelectedTab] = useState<string>();
const handleTabsDidChange = async (event: CustomEvent) => {
setSelectedTab(event.detail.tab);
};
return (
<IonApp>
<IonReactRouter>
<IonTabs onIonTabsDidChange={handleTabsDidChange}>
<IonRouterOutlet>
<Route exact path="/status">
<Status />
</Route>
</IonRouterOutlet>
<IonTabBar slot="bottom">
<IonTabButton tab="status" href="/status">
<IonIcon icon={selectedTab === 'status' ? disc : discOutline} />
<IonLabel>Status</IonLabel>
</IonTabButton>
</IonTabBar>
</IonTabs>
</IonReactRouter>
</IonApp>
);
};

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 close an Angular2 modal with a boolean?

I'm new to html and Angular2. Any help with this problem would be much appreciated.
I am placing a form component inside a ng2-modal and I would like the modal to close when the form returns a boolean from an event.
The form is for adding a new class to a database. Its first usage is on another page where it is not inside a modal.
There, upon clicking cancel/submit in the component, I have it return true and then redirect to another url.
For the new implementation I want the modal to close when the form returns true. The problem is that the save/cancel buttons are in the component containing the form. So I can't just use the modal's click event to close it.
Here is my current code:
<modal #addNewClassModal>
<modal-header>
<h4 class="modal-title"><i class="fa fa-cube"></i> Add a new class</h4>
</modal-header>
<modal-content>
<div>
<add-new-class (closeModal)="finishAddingNewClass($event)">
</add-new-class>
</div>
</modal-content>
</modal>
My problem is that I can't figure out how to get the modals close() method to rely on the boolean.
I've tried putting closeModal="addNewClassModal.close()" in different places and switching around the syntax but its not working and I can't find anything online.
You can pass a reference to addNewClassModal to your AddNewClass component:
<add-new-class [modal]="addNewClassModal">
</add-new-class>
And in your AddNewClass component add Input() for modal:
import { Input } from '#angular/core';
import { ModalDirective } from 'ng2-bootstrap/components/modal';
#Input()
modal: ModalDirective; // you can also set type to any instead of ModalDirective
Then in your component you can close modal with hide() function:
this.modal.hide();