I want to dynamically set a value within my cart constructor. My cart variable has price, item. and size values. I want to assign a value to item dynamically on what item has been clicked. This is my code:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { addCart } from '../../actions';
import { withRouter } from 'react-router';
//import { Cart } from './webcart';
import CamoHat from './camodye.jpeg';
import TonyTape from './TonyTape.png';
import RegularHat from './regularhat.jpg';
import JaguarShirt from './JAGUARLOGO.png';
import SeltzShirt from './seltzshirt.jpg';
import NocHoodie from './NOCNOCHOODIE.png';
export class WebShop extends Component {
constructor(props){
super(props);
this.state = {value: 'medium', cartData: {} };
this.handleClick = this.handleClick.bind(this);
this.change = this.change.bind(this);
this.goProductPage = this.goProductPage.bind(this);
this.goProductPage2 = this.goProductPage2.bind(this);
this.goProductPage3 = this.goProductPage3.bind(this);
}
handleClick() {
let cart = {price:0,item:"userselection",size:this.state.value};
this.props.onCartAdd(cart);
this.itemSelection(cart);
}
change(e){
this.setState({value: e.target.value})
}
itemSelection(cart){
let userItem = cart;
let userSelection = cart
if (userItem == "shirt1") {
let itemPrice = 20.00;
}
}
...
render() {
return (
<div className='Webshop' id='Webshop'>
<ul id="Productlist">
<div className='Product'>
<img src={CamoHat} onClick={this.goProductPage}></img>
<div id='infoname'>NOC NOC HAT (CAMO)</div>
<div id='infoprice'>40.00</div>
</div>
<div className='Product'>
<img src={JaguarShirt} onClick={this.goProductPage2}></img>
<div id='infoname'>JAGUAR PYRAMIDS T-SHIRT</div>
<div id='infoprice'>25.00</div>
</div>
<div className='Product'>
<img src={SeltzShirt} onClick={this.goProductPage3}></img>
<div id='infoname'>JAGUAR PYRAMIDS T-SHIRT</div>
<div id='infoprice'>25.00</div>
</div>
<div className='Product'>
<img src={NocHoodie} onClick={this.goProductPage}></img>
<div id='infoname'>JAGUAR PYRAMIDS T-SHIRT</div>
<div id='infoprice'>25.00</div>
</div>
<div className='Product'>
<img src={RegularHat}></img>
<button onClick={this.handleClick} className="addit">Add to cart</button>
<select id="size" onChange={this.change} value={this.state.value}>
<option value="medium">Medium</option>
<option value="large">Large</option>
<option value="x-large">X-large</option>
</select>
</div>
<div className='Product'>
<img src={TonyTape}></img>
<button onClick={this.handleClick} className="addit">Add to cart</button>
<select id="size" onChange={this.change} value={this.state.value}>
<option value="medium">Medium</option>
<option value="large">Large</option>
<option value="x-large">X-large</option>
</select>
</div>
</ul>
</div>
);
}
}
...
export default connect(mapStateToProps,mapDispatchToProps)(WebShop);
I want to assign the item value in cart using the description of the item within the item div id=infoname (the text itself) for ex: NOC NOC Hat. How can I do this within my function? Is there a better way to do it?
The quickest way to do what you want to do is to use refs :
https://facebook.github.io/react/docs/refs-and-the-dom.html
Quote from the official doc :
The ref attribute takes a callback function, and the callback will be
executed immediately after the component is mounted or unmounted.
When the ref attribute is used on an HTML element, the ref callback
receives the underlying DOM element as its argument
I have removed some lines from your code so that it compiles for me.
Here it is :
https://codesandbox.io/s/314N8jxG9
Look at line 22 and 46. (check the console.log output)
The ref attributes receives a callback that can access the div element, thus it innerHTML value.
This is not the best way to do it but this will fix your issue.
Now the best is to use props.
Please, refactor your code by first extracting your products items into ProductIem this way :
const ProductItdem = ({description, price})=>{
return (
<div className='Product'>
<div id='infoname' >{description}</div>
<div id='infoprice'>{price}</div>
</div>
);
}
You can even compose them in a ProductList Component.
Then you will pass props from you WebShop container component to the dumm components.
Try it and let us know your questions.
Related
I am working on a to do list using React and Typescript. I am trying to return a different colored div when selecting a priority in the option select dropdown (prioritySelect). I have tucked in a function within the ToDoItem JSX Element. What I want to happen is for the prioritySelect component to change the background color of the div it is in "to-do-item" to signify importance.
I tried to add handleOptionsChange function and call it within the div return at the bottom but I keep running into errors when trying to add handleOptionsChange, I am not sure why.
//TODOITEM TO RETURN TO DO COMPONENT
`function ToDoItem(props: { toDo: ToDo; onDeleteToDo: any; prioritySelect: any;}) {`
///TRYING TO CREATE FUNCTION EXPRESSION THAT CALLS EVENT SET STATE FOR PRIORITY BELOW
`handleOptionsChange:any; setState:any;}) {
handleOptionsChange = (event: any) => {
props.setState({
option: event.target.value
});
}`
`return (
<div className="to-do-item" id="to-do-item">
<div className="checkbox-title-container">
<div className="check-title-div">
{Checkbox()}
<h2 className="to-do-title">{props.toDo.title}</h2>
</div>
<div id="delete-div">`
//PRIORITY OPTION SELECT BELOW
`<select name="Priority" className="select-field" value={props.prioritySelect.option} onChange={props.handleOptionsChange}>
<option className="important" value='1'>Important</option>
<option selected value='2'>Normal</option>
</select>
<button id="delete" onClick={props.onDeleteToDo}>
Delete
</button>
</div>
</div>
<div className="description-box">
<span className="description">{props.toDo.description}</span>
</div>
<br />
<span className="to-do-date">
{/* {props.toDo.duedate.toLocaleDateString()} */}
</span>
</div>
);
}`
I am trying to call handleOptionsChange when returning a JSX component below, I have taken out the rest of the components within the to-do-item div for the sake of readability
`<div className="to-do-item" id="to-do-item">
{prioritySelect={handleOptionsChange}} </div>
<div>`
I have a component that generates a random item every time I access the random page. Each time I refresh the page a new random item is generated. I would like to generate a new random item every time I click the button 'pick another', but I'm not entirely sure how this can be done. Any help would be greatly appreciated.
Random.vue
<template>
<div class="details" v-for="item in items" v-bind:key="item.id">
<div class="details-primary u-center-text">
<h1 class="heading-secondary">{{item.name}}</h1>
<p class="tagline--main">{{item.tagline}}</p>
</div>
<div class="details-secondary u-margin-top-big">
<div class="info">
<span class="info__detail info--title">Vol</span>
<span class="info__detail info--spec">{{item.abv}}%</span>
</div>
<img class="details-image" :src='item.image_url' alt="">
<div class="info">
<span class="info__detail info--title">Amount</span>
<span class="info__detail info--spec">1ltr</span>
</div>
</div>
</div>
<div class="rand-gen">
Pick another
</div>
</template>
<script lang="ts">
import {Options, Vue} from 'vue-class-component'
import axios from 'axios';
#Options({
data() {
return{
items: []
}
},
mounted() {
axios.get('https://api.punkapi.com/v2/beers/random')
.then(res => this.items = res.data)
.catch(err => console.log(err));
}
})
export default class Random extends Vue {}
</script>
you have to add #click function and method
html should like this
Pick another
and the method is
methods: {
generate() {
//your code
}
}
I have this Materialize DropDown
<ul id="dropdown1" className="dropdown-content">
<li>
<a href="#!">
one
</a>
</li>
<li>
two
</li>
<li className="divider" tabIndex="-1"></li>
<li>
three
</li>
<li>
<a href="#!">
<i className="material-icons">view_module</i>four
</a>
</li>
<li>
<a href="#!">
<i className="material-icons">cloud</i>five
</a>
</li>
</ul>
and I have declared it as follows :-
componentDidMount() {
let dropdowns = document.querySelectorAll('.dropdown-trigger');
let options = {
inDuration: 300,
outDuration: 300,
hover: true, // Activate on hover
coverTrigger: false, // Displays dropdown below the button
};
M.Dropdown.init(dropdowns, options);
var instance = M.Dropdown.getInstance(dropdowns);
}
which displays fine, however I cannot manage to get the selected value.
I tried the following JQuery:-
$(document).ready(function(){
$('dropdown1').formSelect();
});
but I am getting a type error :-
TypeError: jquery__WEBPACK_IMPORTED_MODULE_6___default(...)(...).formSelect is not a function
Any help will be very much appreciated!
Thanks
I think one should use <Select> in case of a form to select from a list of options. So, you can initialize the Materialize components in componentDidMount() lifecycle method.
I attached onChange event listener on <Select> so that we can track the value and save it in our state. I also gave the defaultValue property so that a person knows in form what he has to choose, for example, Choose a country.
CodeSandbox - Working Demo (Select in React)
Select Component
import React, { Component } from "react";
import M from "materialize-css";
import "materialize-css/dist/css/materialize.min.css";
class Select extends Component {
constructor() {
super();
this.state = {
selectVal: null
};
}
componentDidMount() {
M.FormSelect.init(this.FormSelect);
}
handleChange = event => {
this.setState({
[event.target.name]: event.target.value
});
};
render() {
console.log(this.state.selectVal);
return (
<div className="input-field col s12">
<select
ref={FormSelect => {
this.FormSelect = FormSelect;
}}
name="selectVal"
onChange={this.handleChange}
defaultValue="0"
>
<option value="0" disabled>
Choose your option
</option>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
<label>Materialize Select</label>
</div>
);
}
}
export default Select;
I'm hoping you encounter the same issue of mine. I have react code that need a jquery event like (click, change). here is my code.
export default class SamplePreviewComponent extends React.Component<Props, any> {
constructor(props) {
super(props);
}
componentDidMount() {
this.renderChoiceButton();
}
renderChoiceButton() {
$("input.st").on("click", function() {
let value = $(this).val();
this.props.addDependentSample(value);
});
}
render() {
const { sampleTree } = this.props;
return (
<div className="row pl-1 pr-1 pt-0 mb-1">
<div className="columns bg-black20 pt-1 pb-1 border-radius-sm">
<div className="mb-1">
<p className="subheader">
<strong>
<small>SAMPLE #1</small>
</strong>
</p>
{sampleTree.root.label.trim().length > 0 && <h4>{sampleTree.root.label}</h4>}
{sampleTree.root.subLabel &&
sampleTree.root.subLabel.trim().length > 0 && (
<span className="subheader">
<small>
<strong>{sampleTree.root.subLabel}</strong>
</small>
</span>
)}
</div>
<div>
<div
dangerouslySetInnerHTML={{ __html: sampleTree.root.generatedHtml }}
className="red"
/>
</div>
</div>
</div>
);
}
}
if you check my return value of my component. there is dangerouslySetInnerHTML added. The output is like this
<div>
<div class="fancy-checkbox fancy-hover small mb-0">
<input type="checkbox" class="st" id="_0" name="17[]" value="1">
<label for="_0">1</label>
</div>
<div class="fancy-checkbox fancy-hover small mb-0">
<input type="checkbox" class="qt" id="_1" name="17[]" value="2">
<label for="_1">2</label>
</div>
</div>
When the user click the checkbox. I'm going to add and event using a jquery
renderChoiceButton() {
$("input.st").on("click", function() {
let value = $(this).val();
this.props.addDependentSample(value);
});
}
I get an error Cannot read property 'addDependentSample' of undefined. Maybe, because it comes from the react props and the jquery cannot read it. How can I add event using jquery that will connect the function to react?
There are a few ways you can resolve this error - a simple approach would be to store a reference to your component instance (ie componentInstance as shown below), and then access the component's props through that instance, like so:
renderChoiceButton() {
// Store reference to component for access in click handler
const componentInstance = this;
$('input.st').on('click', function() {
let value = $(this).val();
// Access props for the component via componentInstance
componentInstance.props.addDependentSample(value);
});
}
I have a component that emit event through a bus as indicated below. The same component need to be included twice on another component. I want the events emitted to populate different variables;
//component.vue
<template>
<div>
Hello there?
<a #click="changed">New</a>
<ol>
<li v-for="option in list">
<div class='row justify-content-start'>
<div class='col-sm-6'><input v-model="option.value" type='text' placeholder="key"/></div>
<div class='col-sm-6'><input v-model="option.name" type='text' placeholder="Name"/></div>
</div>
</li>
</ol>
</div>
</template>
<script>
export default{
props:['options','iscolumn'],
data(){
return {list:this.options,item:{name:'',value:''}}
},
methods:{
changed(){
$bus.$emit('add-option',this.item,this.iscolumn);
}
}
}
</script>
/** root.vue **/
<template>
<div>
<h3>Rows</h3>
<div><rows :options="rows" :iscolumn="false"/></div>
<h3>Columns</h3>
<div><rows :options="columns" :iscolumn="true" /></div>
</div>
</template>
<script>
export default{
components:{'rows':require('./component')},
data(){
return {
columns:[],rows:[]
}
},
created(){
this.$bus.$on('add-option',(option,iscolumn)=>{
if (is_column) {this.columns.push(option);}
else this.rows.push(option);
})
}
}
</script>
When I click on the New from root both columns and rows get populated.
Looking for case where each of the component are independent, can't understand how they are sharing variables.
Any assistance will be appreciated.
Assign unique key attributes to the rows components:
<template>
<div>
<h3>Rows</h3>
<div><rows key="rows1" :options="rows" :iscolumn="false"/></div>
<h3>Columns</h3>
<div><rows key="rows2" :options="columns" :iscolumn="true" /></div>
</div>
</template>