My codes (following the example):
class MyCustomBody extends React.Component {
render() {
return (<form>
<div className="form-group"><label>Email</label><input type="text" placeholder="Email" className="form-control editor edit-text"></input></div>
<div className="form-group"><label>Role</label><select placeholder="Role" className="form-control editor edit-select"><option value="Admin">Admin</option><option value="Client">Client</option></select></div>
<div className="form-group"><label>Name</label><input type="text" placeholder="Name" className="form-control editor edit-text"></input></div>
<div className="form-group"><label>Password</label><input type="text" placeholder="Password" className="form-control editor edit-text"></input></div>
</form>);
}
}
class MyDashboard extends Component {
constructor(props) {
super(props);
this.createCustomModalBody = this.createCustomModalBody.bind(this);
}
createCustomModalBody() {
return <MyCustomBody/>;
}
render() {
const options = {
insertModalBody: this.createCustomModalBody
};
return (
<BootstrapTable data={(this.props.users || [])}
options={options}
insertRow
search >
<TableHeaderColumn isKey dataField='_id'>ID</TableHeaderColumn>
<TableHeaderColumn dataField='email'>Email</TableHeaderColumn>
<TableHeaderColumn dataField='role'>Role</TableHeaderColumn>
<TableHeaderColumn dataField='profile' dataFormat={this.nameFormatter}>Name</TableHeaderColumn>
<TableHeaderColumn dataField='password' hidden>Password</TableHeaderColumn>
</BootstrapTable>
);
}
}
Some codes removed. When +new button clicked, the default form shown instead of my customized form. Any ideas? Thanks
Related
I am using supabase auth helper package in my project. When the user enters the login details it should be redirected to the order page. I am using supabase auth condition in the order page. But when the user enters the login details it is not redirected to the order page.
code for the authentication in the order-page is given below :-
export const getServerSideProps = withPageAuth({ redirectTo: '/admin/login',
async getServerSideProps(ctx) {
// Access the user object
const { user, accessToken } = await getUser(ctx);
return { props: { email: user?.email } };
}
});
login page code is given below:-
async function handleSubmit(e) {
e.preventDefault();
const { user, error } = await supabase.auth.signIn({
email,
password
})
router.push('/orders')
}
return (
<Layout>
<div className="flex items-center justify-center h-screen">
<form onSubmit={handleSubmit}>
<p className="text-center text-[27px] text-white">Admin Login</p>
<div className="mt-4 text-white">
<p className="text-[14px]">Email</p>
<input type="text" className="bg-[#4A4949] rounded-md py-2 px-1 w-[300px]"
placeholder="Email Address"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div className="mt-4 text-white">
<p className="text-[14px]">Password</p>
<input type="password" className="bg-[#4A4949] rounded-md py-2 px-1 w-[300px]"
placeholder="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<button className="mt-8 bg-[#4A4949] text-white rounded w-[300px] py-2">Login</button>
</form>
</div>
</Layout >
)
}
You will need to wait for the user object to be defined before calling router.push:
import { useUser } from '#supabase/supabase-auth-helpers/react';
const { user } = useUser();
useEffect(() => {
if (user) {
router.push('/orders');
}
}, [user]);
async function handleSubmit(e) {
e.preventDefault();
const { user, error } = await supabase.auth.signIn({
email,
password
})
}
import React, { Fragment, useState, useEffect } from "react";
import { useSelector, useDispatch, connect } from "react-redux";
import { useNavigate } from "react-router";
import { Field, Form, Formik } from "formik";
import VisibilityIcon from "#material-ui/icons/Visibility";
import VisibilityOffIcon from "#material-ui/icons/VisibilityOff";
import { changePassword } from "../../Redux/Actions/changePasswordAction";
import { passwordErrors, roles } from "../Shared/constants";
import Alert from "../Modal/modal";
import "./ChangePassword.css";
function ChangePassword() {
const [showPassword1, setShowPassword1] = useState(false);
const [showPassword2, setShowPassword2] = useState(false);
const [showPassword3, setShowPassword3] = useState(false);
const alert = useSelector((state) => state.alert);
enter code here
const role_id = localStorage.getItem("role_id");
//Redux Dispatch:
const dispatch = useDispatch();
//Used to navigate
const navigation = useNavigate();
const passwords = {
currentPassword: "",
newPassword: "",
confirmNewPassword: "",
};
// function toggleShowPassword(clickedField) {
// if (clickedField === showPassword1) {
// setShowPassword1(!showPassword1) &&
// setShowPassword2(showPassword2) &&
// setShowPassword3(showPassword3);
// } else if (clickedField === showPassword2) {
// setShowPassword2(!showPassword2) &&
// setShowPassword1(showPassword1) &&
// setShowPassword3(showPassword3);
// } else {
// setShowPassword3(!showPassword3) &&
// setShowPassword1(showPassword1) &&
// setShowPassword2(showPassword2);
// }
// }
function toggleShowPassword1() {
setShowPassword1(!showPassword1);
}
function toggleShowPassword2() {
setShowPassword2(!showPassword2);
}
function toggleShowPassword3() {
setShowPassword3(!showPassword3);
}
//Alert
useEffect(() => {
if (Number(role_id) === roles.TRAINER_ROLE_ID) {
if (alert.type === "success_clear") {
navigation("/trainer-profile");
}
} else {
if (alert.type === "success_clear") {
navigation("/user-profile");
}
}
}, [alert, navigation, role_id]);
function validate(passwords) {
const errors = {};
if (passwords.currentPassword === "") {
errors.currentPassword = passwordErrors.PASSWORD;
}
if (passwords.newPassword === passwords.currentPassword) {
errors.newPassword = passwordErrors.OLD_NEW_SAME;
}
if (passwords.newPassword === "") {
errors.newPassword = passwordErrors.PASSWORD;
} else if (
!/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!##%&])(?=.{8,})/.test(
passwords.newPassword
)
) {
errors.newPassword = passwordErrors.PASSWORD_INVALID;
}
if (passwords.confirmNewPassword === "") {
errors.confirmNewPassword = passwordErrors.CONFIRM_PASSWORD;
} else if (passwords.confirmNewPassword !== passwords.newPassword) {
errors.confirmNewPassword = passwordErrors.PASSWORDS_UNMATCHED;
}
return errors;
}
function handleChangePassword(passwords) {
const id = localStorage.getItem("user_id");
const passwordsData = {
oldPassword: passwords.currentPassword,
password: passwords.confirmNewPassword,
};
dispatch(changePassword(id, passwordsData));
}
return (
<Fragment>
<div className="row">
<div className="col">
<span className="main-heading mx-4">Change Account Password</span>
<div className="mx-4">
<hr></hr>
</div>
</div>
</div>
{alert.message && <Alert show={true} />}
<div className="passwords">
<Formik
initialValues={passwords}
validate={(values) => validate(values)}
onSubmit={(values) => handleChangePassword(values)}
>
{({ errors, touched }) => (
<Form>
<div className="row">
<div className="col-md">
<div className="form-group mb-4">
<label htmlFor="currentPassword" className="cp-label">
Current Password
</label>
<div className="input-group">
<Field
type={showPassword1 ? "text" : "password"}
id="currentPassword"
name="currentPassword"
placeholder="Enter your Current password"
className={
errors.currentPassword && touched.currentPassword
? "form-control primary-input-field is-invalid pass"
: "form-control primary-input-field pass"
}
/>
<span
className="input-group-text"
id="basic-addon2"
// onClick={() => toggleShowPassword(showPassword1)}
onClick={toggleShowPassword1}
>
{showPassword1 ? (
<VisibilityIcon
fontSize="small"
className="iconColor"
/>
) : (
<VisibilityOffIcon
fontSize="small"
className="iconColor"
/>
)}
</span>
{touched.currentPassword && errors.currentPassword ? (
<div className="invalid-feedback">
{errors.currentPassword}
</div>
) : null}
</div>
</div>
</div>
</div>
<div className="row">
<div className="col-md">
<div className="form-group mb-4">
<label htmlFor="newPassword" className="cp-label">
New Password
</label>
<div className="input-group">
<Field
type={showPassword2 ? "text" : "password"}
id="newPassword"
name="newPassword"
placeholder="Enter your New password"
className={
errors.newPassword && touched.newPassword
? "form-control primary-input-field is-invalid pass"
: "form-control primary-input-field pass"
}
/>
<span
className="input-group-text"
id="basic-addon2"
// onClick={() => toggleShowPassword(showPassword2)}
onClick={toggleShowPassword2}
>
{showPassword2 ? (
<VisibilityIcon
fontSize="small"
className="iconColor"
/>
) : (
<VisibilityOffIcon
fontSize="small"
className="iconColor"
/>
)}
</span>
{touched.newPassword && errors.newPassword ? (
<div className="invalid-feedback">
{errors.newPassword}
</div>
) : null}
</div>
</div>
</div>
</div>
<div className="row">
<div className="col-md">
<div className="form-group mb-4">
<label htmlFor="confirmNewPassword" className="cp-label">
Confirm New Password
</label>
<div className="input-group">
<Field
type={showPassword3 ? "text" : "password"}
id="confirmNewPassword"
name="confirmNewPassword"
placeholder="Confirm your New password"
className={
errors.confirmNewPassword &&
touched.confirmNewPassword
? "form-control primary-input-field is-invalid pass"
: "form-control primary-input-field pass"
}
/>
<span
className="input-group-text"
id="basic-addon2"
// onClick={() => toggleShowPassword(showPassword3)}
onClick={toggleShowPassword3}
>
{showPassword3 ? (
<VisibilityIcon
fontSize="small"
className="iconColor"
/>
) : (
<VisibilityOffIcon
fontSize="small"
className="iconColor"
/>
)}
</span>
{touched.confirmNewPassword &&
errors.confirmNewPassword ? (
<div className="invalid-feedback">
{errors.confirmNewPassword}
</div>
) : null}
</div>
</div>
</div>
</div>
<div className="row mt-4">
<div className="col text-end">
<button className="btn primary-button" type="submit">
Change Password
</button>
</div>
</div>
</Form>
)}
</Formik>
</div>
</Fragment>
);
}
const mapStateToProps = (state) => ({
changePassword: state.changePassword,
});
export default connect(mapStateToProps, {
changePassword,
})(ChangePassword);
Please someone help me to apply only one function that can toggle show and hide for three fields, I have already tried one function but it's not working. I couldn't know what to do ? I need one function there to toggle eye symbol when it is clicked, but with the function I have used it's changing and I am pressing for one field and another field's being shown, please someone explain me
I created an input component to reuse it between a few forms. In one of then, it's working perfectly, but in the other, it's not.
It doesn't throw any erros. I even receive the input value after submit.
code.component.html
<div [ngClass]="aplicaCssErro(ag)">
<label for="code">Code</label>
<input id="code" name="code" type="text" class="form-control" [(ngModel)]="value" required #ag="ngModel"
maxlength="4" minlength="4" (blur)="formatCode(ag)">
<div *ngIf="verificaValidTouched(ag)" class="msgErroText">
<gce-campo-control-erro [mostrarErro]="ag?.errors?.required" msgErro="the code is required">
</gce-campo-control-erro>
</div>
code.component.ts
import { Component, OnInit, Input } from '#angular/core';
#Component({
selector: 'gce-input-code',
templateUrl: './input-code.component.html',
styleUrls: ['./input-code.component.scss']
})
export class InputCodeComponent implements OnInit {
#Input() value: string = "";
constructor() { }
ngOnInit() {
}
//some functions
}
form.component.html
The problem is that the form is not validating it, just the first input.
I think the form is not recognizing it as one of it's inputs.
<form (ngSubmit)="onSubmitForm2(f)" #f="ngForm">
<div class="row">
<div class="col-sm-6" [ngClass]="aplicaCssErro(apelido)">
<label for="apelido">Apelido da conta</label>
<input id="apelido" name="apelido" type="text" class="form-control" alt="Apelido" [(ngModel)]="conta.apelido" required #apelido="ngModel">
<div *ngIf="verificaValidTouched(apelido)" class="msgErroText">
<gce-campo-control-erro [mostrarErro]="apelido?.errors?.required" msgErro="O Apelido é obrigatório.">
</gce-campo-control-erro>
</div>
</div>
</div>
<div class="row">
<div class="form-group">
<div class="col-sm-2">
<gce-input-code name="code" [(ngModel)]="user.code" #code="ngModel" ngDefaultControl></gce-input-code>
</div>
</div>
</div>
<div class="row">
<button class="btn btn-default" name="btn2" type="submit" alt="Continuar" [disabled]="!f.valid">Continue</button>
</div>
Any help?
If I understand your question correctly. You are trying to make it so the form(ngForm) can validate the custom component that wraps around the input(gce-input-code).
A normal form does not have any way to know what is going in/out of the component as it is Angular component. You would have to enhance your code.component.ts to include all the connectors (ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS) into it.
Checkout this blog
https://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html#custom-form-control-considerations
and its plnkr(exerpt code below)
https://plnkr.co/edit/6xVdppNQoLcsXGMf7tph?p=info
import { Component, OnInit, forwardRef, Input, OnChanges } from '#angular/core';
import { FormControl, ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS }
from '#angular/forms';
export function createCounterRangeValidator(maxValue, minValue) {
return (c: FormControl) => {
let err = {
rangeError: {
given: c.value,
max: maxValue || 10,
min: minValue || 0
}
};
return (c.value > +maxValue || c.value < +minValue) ? err: null;
}
}
#Component({
selector: 'counter-input',
template: `
<button (click)="increase()">+</button> {{counterValue}} <button (click)="decrease()">-</button>
`,
providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CounterInputComponent), multi: true },
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => CounterInputComponent), multi: true }
]
})
export class CounterInputComponent implements ControlValueAccessor, OnChanges {
propagateChange:any = () => {};
validateFn:any = () => {};
#Input('counterValue') _counterValue = 0;
#Input() counterRangeMax;
#Input() counterRangeMin;
get counterValue() {
return this._counterValue;
}
set counterValue(val) {
this._counterValue = val;
this.propagateChange(val);
}
ngOnChanges(inputs) {
if (inputs.counterRangeMax || inputs.counterRangeMin) {
this.validateFn = createCounterRangeValidator(this.counterRangeMax, this.counterRangeMin);
this.propagateChange(this.counterValue);
}
}
writeValue(value) {
if (value) {
this.counterValue = value;
}
}
registerOnChange(fn) {
this.propagateChange = fn;
}
registerOnTouched() {}
increase() {
this.counterValue++;
}
decrease() {
this.counterValue--;
}
validate(c: FormControl) {
return this.validateFn(c);
}
}
I have API which consists
"pictures": [
"http:\/\/storage\/web\/source\/images\/2016-10-28\/edac054f88fd16aee7bc144545fea4b2.jpg",
"http:\/\/storage\/web\/source\/images\/2016-10-28\/9aa3217f37f714678d758de6f7f5222d.jpg",
"http:\/\/storage\/web\/source\/images\/2016-10-28\/5164ed92c205dc73a37d77e43fe1a284.jpg"
]
I have to render these pictures in Carousel. The problem is I have no idea how to render that pictures from an array, means that each picture should be outputted in each slider separately.
That is my code:
const API = 'http://...';
export default class Api extends React.Component {
constructor(props) {
super(props)
this.state = {
slider_pics:[
],
}
}
fetchProfile(id) {
let url = `${API}${name}`;
fetch(url)
.then((res) => res.json() )
.then((data) => {
this.setState({
slider_pics:data.data.pictures,
})
})
.catch((error) => console.log(error) )
}
componentDidMount() {
this.fetchProfile(this.state.name);
}
render() {
return (
<div>
<div>
<Carousel data={this.state}/>
</div>
</div>
)
}
}
export default class Carousel extends React.Component {
render() {
let data = this.props.data;
return(
<div>
<React_Boostrap_Carousel animation={true} className="carousel-fade">
<div >
<img style={{height:500,width:"100%"}} src={data.slider_pics} />
</div>
<div style={{height:500,width:"100%",backgroundColor:"aqua"}}>
456
</div>
<div style={{height:500,width:"100%",backgroundColor:"lightpink"}}>
789
</div>
</React_Boostrap_Carousel>
</div>
)
}
};
In this code all the URL images are rendering in one slide, I need each picture renders separately in each slide. Please help.
I almost figured out on my own. In Carousel component we have to set the loop in constructor and return that loop in map. Shortly, this is my code that is working for 100%
export default class Carousel extends React.Component {
constructor(props) {
super(props);
const slider_pics=[];
for (let i = 0; i < 10; i++) {
slider_pics.push(<React_Boostrap_Carousel />);
}
this.state = {slider_pics};
}
render() {
let data = this.props.data;
return(
<div>
<React_Boostrap_Carousel animation={true} className="carousel-fade">
{data.slider_pics.map((slider_pic, index) => (
<div key={index}>
<img style={{heght:200, width:1000}} src={slider_pic} />
</div>
))}
</React_Boostrap_Carousel>
</div>
)
}
};
The API component will be the same, just need to update the Carousel component like code above
I did example where my react fetches data from API.
I have the following mockup
List of objects
-- Object
--- Select field
this is my OrdersList.jsx
import React from 'react';
import Order from './Order';
class OrdersList extends React.Component {
constructor(props) {
super(props)
this.state = { data: [] }
}
componentDidMount() {
$.ajax({
url: '/api/v1/orders',
success: data => this.setState({ data: data }),
error: error => console.log(error)
})
}
render() {
return (
<div className="row">
<div className="col s12">
<table className="floatThead bordered highlight">
<thead>
<tr>
<th>id</th>
<th>status</th>
</tr>
</thead>
<Order data = { this.state.data } />
</table>
</div>
</div>
)
}
}
export default OrdersList;
here is my Order.jsx (it has Item to list and ItemStatus)
import React from 'react'
class OrderStatus extends React.Component {
constructor(props) {
super(props)
this.state = { data: [] }
}
handleChange(event) {
let data = {
order: {
status: event.target.value
}
}
console.log(event)
$.ajax({
method: 'PUT',
url: `/api/v1/orders/${event.target.id}`,
data: data,
success: data => (console.log(data), this.setState({ data: data })),
error: error => console.log(error)
})
}
render() {
return (
<div className="row">
<div className="input-field">
<p>status: {this.props.data.status}</p>
<select value={ this.props.data.status } id={ this.props.data.id } onChange={ this.handleChange } className="browser-default" >
<option value='neworder'>new</option>
<option value='pendingorder'>pending</option>
<option value='sentorder'>sent</option>
<option value='completedorder'>done</option>
</select>
</div>
</div>
)
}
}
class Order extends React.Component {
constructor(props) {
super(props)
this.state = { data: [] }
}
render() {
return (
<tbody>
{
this.props.data.map(
order =>
<tr key={order.id}>
<td>
# {order.id}
</td>
<td>
<OrderStatus data={ order } />
</td>
</tr>
)
}
</tbody>
)
}
}
export default Order;
What I am not able to understand is how to update my item status on ajax callback (there is update in backend, it works just fine, but how to update my status state on child item which is being listed by map function).. Appreciate for your input!
Your code looks fine, you are just missing a bind statement.
Add the following to your constructor and it should work:
this.handleChange = this.handleChange.bind(this);
For reference check this link.