MDC-web not working as expected - javascript

import React, { Component } from "react";
import { MDCTextfield, MDCTextfieldFoundation } from "#material/textfield";
import { MDCFormField, MDCFormFieldFoundation } from "#material/form-field";
class Material extends React.Component {
constructor(props) {
super(props);
this.state = {};
this.textfield_ = new MDCTextfieldFoundation(
document.querySelector(".mdc-textfield")
);
}
componentDidMount() {
const textfield = new MDCTextfield(
document.querySelector(".mdc-textfield")
);
}
render() {
return (
<div>
<form>
<div className="mdc-textfield">
<input type="email" id="" className="mdc-textfield__input" />
<label htmlFor="email" className="mdc-textfield__label">
Email address1
</label>
</div>
<div className="mdc-textfield">
<input type="email" id="email" className="mdc-textfield__input" />
<label htmlFor="email" className="mdc-textfield__label">
Email address3
</label>
</div>
</form>
</div>
);
}
}
export default Material;
this is my page Material.js in my project and here i'm using material-components-web library.I want input to animate which was working fine.
but i wanted to use two inputs with same animation.i used two identical div of class mdc-textfield.But now only 1st div with class mdc-textfield is working fine but 2nd shows no animation.please help

This is because document.querySelector(".my_class") returns the first elements that it finds with "my_class". You can uses different ref names for the textfiels like this:
componentDidMount() {
const textfield_email = new MDCTextfield(this.refs.textfield_email);
const textfield_name = new MDCTextfield(this.refs.textfield_name);
}
...
<label ref="textfield_email" className="mdc-textfield ">
<input name="email" className="mdc-textfield__input" onChange={this.handleChange} value={this.state.email} />
<span className="mdc-textfield__label">Email</span>
</label>
<label ref="textfield_name" className="mdc-textfield ">
<input name="name" className="mdc-textfield__input" onChange={this.handleChange} value={this.state.name} />
<span className="mdc-textfield__label">Name</span>
</label>
I usually wrap the MDC Components in React JS Components. Here would be a very stripped down example for a textfield:
import React from 'react';
import { MDCTextfield } from '#material/textfield/dist/mdc.textfield';
class Textfield extends React.Component {
componentDidMount() {
const textfield = new MDCTextfield(this.refs.textfield);
}
static defaultProps = {
label: "",
className: "",
name: "",
onChange: function() {}
}
render() {
return (
<div className={this.props.className}>
{/* Text field component */}
<label ref="textfield" className="mdc-textfield " id={this.props.id} >
<input name={this.props.name} className="mdc-textfield__input" onChange={this.props.onChange} value={this.props.value} />
<span className="mdc-textfield__label">{this.props.label}</span>
</label>
</div>
);
}
}
export default Textfield
Then use like this:
<Textfield onChange={this.handleChange} value={this.state.value} label="email" name="email"></Textfield>
EDIT
If you want to use MDC with ReactJS and want an easy life, I would suggest using: RMWC (https://github.com/jamesmfriedman/rmwc) and hopefully soon the official React Wrapper from Google (https://github.com/material-components/material-components-web-react)

Related

Create a reusable Form Input component with React & TypeScript

How can I define input attributes in typescript? I have an AddUser Component and TextInput Component, I want to import the TextInput component inside the AddUser component and then pass props to the TextInput component.
AddUser.tsx
import Button from '../Shared/Form/Button/Button';
import Form from '../Shared/Form/Form';
import TextArea from '../Shared/Form/TextArea/TextArea';
import TextInput from '../Shared/Form/TextInput/TextInput';
const AddUser = () => {
return (
<div>
<h1>Add User</h1>
<Form method="post" className={'user-form'}>
<TextInput label={'Name'} type="text" name="name" required />
<TextInput label={'Email'} type="email" name="email" required />
<TextInput label={'Country'} type="text" name="country" required />
<TextInput label={'Phone'} type="text" name="phone" required />
<TextArea label={'Address'} name="address" cols="30" rows="4" />
<div className="form-button">
<Button type={'submit'} className={'btn-add'}>
Add
</Button>
<Button type={'submit'} className={'btn-close'}>
Cancel
</Button>
</div>
</Form>
</div>
);
};
export default AddUser;
TextInput.tsx
const TextInput = ({ className, label, ...rest }: { className: string; label: string }) => {
return (
<div className={`${className} form-field`}>
<label htmlFor={label}>{label}</label>
<input {...rest} />
</div>
);
};
export default TextInput;
You can extend HTMLProps which comes with react:
import { HTMLProps } from "react";
interface MyCOmponentProps extends HTMLProps<HTMLInputElement> {
{...}
}
This is how we can make a reusable component. maybe I missed something in onChangeAction according to type script. please let me know me in the comment section so that i can help you better
Example codesandbox
const AddUser = () => {
return (
<div>
<h1>Add User</h1>
<form method="post" className={"user-form"}>
<TextInput
label={"Name"}
placeholder="Name"
type="text"
name="name"
required
/>
<TextInput
label={"Email"}
placeholder="Email"
type="email"
name="email"
required
/>
<TextInput
label={"Country"}
placeholder="Country"
type="text"
name="country"
required
/>
<TextInput
label={"Phone"}
placeholder="Phone"
type="text"
name="phone"
required
/>
</form>
</div>
);
};
export default AddUser;
const TextInput = ({
className,
label,
value,
type,
onChangeAction,
placeholder
}) => {
return (
<div className={`${className} form-field`}>
<label htmlFor={label}>{label}</label>
<input
placeholder={placeholder || "Text"}
type={type || "text"}
value={value}
onChange={onChangeAction}
/>
</div>
);
};

useState not working with render in React app

I am a beginner in React and trying to make a CRUD app. I have this code snipped where useState is being used but when I use the same in a class with render function it gives an error. Can someone explain me why and can convert this code to suit a class with render
export default function App(){
const[userName,setUserName]=useState('');
const[password,setPassword]=useState('');
return(
<div className="CreatePost">
<label>UserName</label>
<input type="text"
onChange={(e)=>{
setUserName(e.target.value);
}}
/>
<label>Password</label>
<input type="text"
onChange={(e)=>{
setPassword(e.target.value);
}}
/>
</div>
);
}
useState() only works in functional component. if you want to modify state in a class based component you have to do it with setState method. Something like this should work
export default class App extends React.Component{
constructor() {
this.state ={ userName : "" , password: "" }
}
render() {
return(
<div className="CreatePost">
<label>UserName</label>
<input type="text"
onChange={(e)=>{
this.setState( {userName : e.target.value} );
}}
/>
<label>Password</label>
<input type="text"
onChange={(e)=>{
this.setState( {password : e.target.value} );
}}
/>
</div>
);
}
}
You cannot use hook inside class component. Convert your existing component into the class based as following:
class App extends React.PureComponent {
state = {
userName: '',
password: '',
}
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value,
});
}
render () {
const { userName, password } = this.state;
return (
<div className="CreatePost">
<label>UserName</label>
<input type="text" value={userName} onChange={this.handleChange}/>
<label>Password</label>
<input type="text" value={password} onChange={this.handleChange}/>
</div>
)
}
}

Why css file of one component interacted with the css file of another component in ReactJS? How to handle it?

I am trying to make a website template with Reactjs. In the Jumbotron section i make subscription form and in the home section User Entry form. But the css of one component interacted with another's one. How can i handle it?
[1]: https://i.stack.imgur.com/Wd4OQ.png
User EntryJs:-
import React, { Component } from 'react'
import './User Entry.css'
class Form extends Component {
initialState = {
name: "",
age: "",
job: ""
}
state = this.initialState
changeHandler = event => {
const { name, value } = event.target
this.setState({
[name]: value
})
}
render() {
const { name, job, age } = this.state
return (
<form className="form-inline">
<div className="row">
<div className="col-md-3">
<div className="form-group">
<label htmlFor="name">Name:-</label>
<input type="text"
className="form-control"
name="name"
id="name"
value={name}
autoFocus
onChange={this.changeHandler} />
</div>
</div>
<div className="col-md-3">
<div className="form-group">
<label htmlFor="age">Age:-</label>
<input type="text"
className="form-control"
name="age"
id="age"
value={age}
autoFocus
onChange={this.changeHandler} />
</div>
</div>
<div className="col-md-3">
<div className="form-group">
<label htmlFor="job">Job:-</label>
<input type="text"
className="form-control"
name="job"
id="job"
value={job}
autoFocus
onChange={this.changeHandler} />
</div>
</div>
<div className="col-md-3"></div>
</div>
</form>
)
}
}
export default Form
Header JS:-
import React, { Component } from 'react'
import './Header.css'
import { Link, withRouter } from "react-router-dom";
class Header extends Component {
constructor(props) {
super(props)
this.state = {
email: ""
}
}
submitHandler = event => {
event.preventDefault();
alert(`Subscribed Email is : ${this.state.email}`);
}
changeHandler = event => {
this.setState({
email: event.target.value
})
}
render() {
return (
// Navbar Starts
<div>
<div className="row navbar">
<Link to="/" style={{textDecoration:'none'}}><div className="col-md-2 logo">ReactApp</div></Link>
<div className="col-md-6"></div>
<Link to="/" style={{textDecoration:'none'}}> <div className="col-md-1 link"> Home</div> </Link>
<Link to="/about" style={{textDecoration:'none'}}> <div className="col-md-1 link"> About</div> </Link>
<Link to="/counter" style={{textDecoration:'none'}}> <div className="col-md-1 link"> Counter </div></Link>
<Link style={{textDecoration:'none'}}><div className="col-md-1 link">Login</div></Link>
</div>
<div className="jumbotron text-center">
<h1>React-App</h1>
<p>We specialize in <strong>Web Development</strong></p>
{/* Subscribing form starts*/}
<form className="form-inline subscribingForm" onSubmit={this.submitHandler}>
<div className="input-group">
<input type="email"
className="form-control"
value={this.state.email}
onChange={this.changeHandler}
size="80"
placeholder="Email..."
required />
<div className="input-group-btn">
<input type="submit" value="Subscribe" className="subscribingBtn" />
</div>
</div>
</form>
{/* Subscribing form closes*/}
</div>
</div>
)
}
}
export default withRouter(Header);
Where is the .css file loaded, in the root component? It probably is loaded globally and is used on every component.Better use JSS (https://cssinjs.org/?v=v10.3.0)
In general react transpiles all the css and add it in to tag.
And as result you one file css conflicts with other.
If you want to avoid this, you can use modular css.
https://create-react-app.dev/docs/adding-a-css-modules-stylesheet/

Simple Redux-Form Component returns undefined

Just created this form as part of a tutorial. However, my console log is giving me undefined whenever I submit the form. What am I doing wrong?
import React, {Component} from 'react';
import { reduxForm } from 'redux-form';
class Signin extends Component {
handleFormSubmit({email, password}) {
console.log(email); // this gives me 'undefined'
}
render() {
const {handleSubmit, fields: {email, password}} = this.props;
return (
<form onSubmit={handleSubmit(this.handleFormSubmit.bind(this))}>
<fieldset className="form-group">
<label>Email:</label>
<input {...email} className="form-control" />
</fieldset>
<fieldset className="form-group">
<label>Password:</label>
<input {...password} className="form-control" />
</fieldset>
<button action="submit" className="btn btn-primary">Sign in</button>
</form>
);
}
}
export default reduxForm({
form: 'signin',
fields: ['email', 'password']
})(Signin);
This is due to an update to redux-form.
Rather than importing the values of {email, password} from this.props we instead use a Field component imported from redux-form.
import { Field, reduxForm } from 'redux-form';
Then using it in place of the input tag you have:
<fieldset className="form-group">
<label>Email:</label>
<Field
name="email"
className="form-control"
component="input"
type="text"
placeholder="Email"
/>
</fieldset>
The connection of this input to redux-form now comes from the name property instead of extracting it from this.props
Important to note: that the name MUST be the same as the name in the fields: [] array defined in the reduxForm:
export default reduxForm({
form: 'signin',
fields: ['email', 'password']
})(Signin);
Building on this, if you want to customise the component that the Field uses, you can define your own custom component pretty easily.
Instead of supplying a string to Field's component property, you can define a function:
<div className="form-group">
<label>Last name:</label>
<Field type="text" className="form-control" placeholder="Smith" name="lastName"
component={textField} />
</div>
textField is imported from another file: import {textField} from '../../redux_form_elements';
And textField is as follows:
import React from 'react';
export const textField = (field) => (
<div>
<input className="form-control" {...field.input} type={field.type} placeholder={field.placeholder} />
{field.meta.touched && field.meta.error &&
<label id="basic-error" className="validation-error-label">This field is required.</label>
}
</div>
);
This looks like the Grider Tutorial. I fixed it this way, with a renderInput function which takes the field. Not sure if this is useful for you.
import React, {Component} from 'react';
import { reduxForm } from 'redux-form';
import { Field } from 'redux-form';
const renderInput = field => (
<div>
<input {...field.input} type={field.type} className="form-control" />
{field.meta.touched && field.meta.error}
<span>{field.meta.error}</span>
</div>
);
class Signin extends Component {
handleFormSubmit({email, password}) {
console.log(email);
console.log("Hi");
}
render() {
const {handleSubmit, fields: {email, password}} = this.props;
return (
<form onSubmit={handleSubmit(this.handleFormSubmit.bind(this))}>
<fieldset className="form-group">
<label>Email</label>
<Field
name="email"
component={renderInput}
type="text" />
</fieldset>
<fieldset className="form-group">
<label>Password</label>
<Field
name="password"
component={renderInput}
type="text" />
</fieldset>
<button action="submit" className="btn btn-primary">Sign in</button>
</form>
);
}
}
export default reduxForm({
form: 'signin',
fields: ['email', 'password']
})(Signin);

onClick not working in alert?

I seem to be doing something wrong trying to listen to an event. I have given an alert in input box but even that doesn't seem to work. What could be the cause for that?
import React from 'react';
class PersonalDetails extends React.Component {
constructor(props) {
super(props);
console.log('PersonalDetails constructor......');
console.log(props);
this._handleTextChange = this._handleTextChange.bind(this);
this._handleSave = this._handleSave.bind(this);
}
_handleTextChange(event) {
this.props.onChange(event);
}
_handleSave(event) {
this.props.onSave(event);
}
render() {
return (
<div >
<h2 className="title" >Your Contact Details </h2>
<h2> Your name </h2>
<label for="Firstname">First Name: </label>
<input name="firstname"
value={this.props.firstname}
type="text"
onChange={this._handleTextChange}>
</input>
<input
type="image"
alt="Confirm"
name="confirm"
src="/myaccount/btnConfirm.gif"
//onClick={this._handleSave}/>
onClick={function(){alert("Hello World!")}}/>
<br/>
<br/>
<div className="line"></div>
</div>
);
}
}
export default PersonalDetails;

Categories

Resources