Undefined value with customized radio input using react-hook-form - forms

I want to make radio button input forms without radio button circles. I am able to make the interface of the form, but the form is sending undefined data.
Additionally, I added CSS that put a solid black border when radio buttons are checked, but this is not working either.
If I remove the CSS display: none, the form works fine; the data shows value, not undefined.
can anyone help me with this? Thank you so much in advance!
The form consists of three components
CustomRadioBtn.module.css
.radioInput + .radioLabel:before{
content: "";
display: inline-block;
background-size: contain;
width: 140px;
height: 140px;
}
.radioLabel {
border-radius: 10px;
color: gray;
cursor: pointer;
margin: auto;
position: relative;
text-align: center;
transition: 0.5s;
}
.radioInput[value="slept less than 7hrs"]+.radioLabel:before{
background-image: url(../../../public/images/sleep/lessThan7hrs.png);
}
.radioInput[value="slept more than 7hrs"]+.radioLabel:before{
background-image: url(../../../public/images/sleep/moreThan7hrs.png);
}
/* below styling is not working */
.radioInput:checked + .radioLabel::before{
border: 3px solid #000;
}
.radioInput{
display: none;
}
CustomeIconContainer.tsx
import { Controller, useForm } from "react-hook-form";
import styled from "styled-components";
import CustomIconInputForm from "../molecules/CustomIconInputForm";
import StyledFlexboxRow from "components/layouts/Flexbox/StyledFlexboxRow";
type Tdata = {
sleep?: string;
stool?: string;
movement?: string;
};
interface IContainerProps {
name: string;
options: string[];
desc: string;
iconLog?: TIconValueData;
}
export type TIconValueData = {
id?: number;
sleep?: string;
movement?: string;
stool?: string;
};
/**
* CustomIconContainer - handle icon input
*/
const CustomIconContainer = (props: IContainerProps) => {
const { name, options, desc } = props;
const { handleSubmit, control } = useForm();
const onSubmit = (data: Tdata) => {
if (data === undefined) {
throw new Error("your log is undefined");
}
console.log(data);
};
const StyledLabel = styled.label`
display: block;
`;
return (
<div className="CustomIconContainer">
<form onSubmit={handleSubmit(onSubmit)}>
<StyledLabel>{desc}</StyledLabel>
{/* mapping icon buttons */}
<StyledFlexboxRow>
{options.map((option, index) => (
<Controller
key={index}
name={name}
control={control}
render={({ field: { onChange, ref, ...props } }) => (
<CustomIconInputForm
{...props}
onChange={onChange}
value={option}
inputRef={ref}
desc={option}
/>
)}
/>
))}
</StyledFlexboxRow>
<button type="submit">Save</button>
</form>
</div>
);
};
export default CustomIconContainer;
CustomIconInputForm.tsx
import { IconDefinition } from "#fortawesome/fontawesome-common-types";
import { RefCallBack } from "react-hook-form";
import styles from "./CustomRadioBtn.module.css";
interface ICustomIconProps {
onChange?: () => void;
name?: string;
value?: string;
icon?: IconDefinition;
desc: string;
inputRef?: RefCallBack;
}
const CustomIconInputForm = (props: ICustomIconProps) => {
const { name, onChange, inputRef, value } = props;
const onChangeHandler = () => {
if (value !== undefined) {
onChange && onChange();
}
};
return (
<span className="CustomIconInputForm">
<input
ref={inputRef}
name={name}
value={value}
onChange={() => {
onChangeHandler;
}}
type="radio"
{...props}
className={styles.radioInput}
/>
<label htmlFor={name} className={styles.radioLabel}>
</label>
</span>
);
};
export default CustomIconInputForm;
no radio button circles
with radio button circles

Related

I make mistakes in Next js, but I dont know where

I use Next js dont correct, but I dont understend why. I saw github repository other programers, but I dont see where I made mistakes. That I make mistakes tolt me employer. The only one differences I found is I use only globals.css, but I think it dont mitakes. I want to grow as a programer, but I cant become better whisout your help. Please told me where i make mistakes in Next js.
My github repository: https://github.com/Yury11111111111/books-catalog
Code:
componets/BookComponent.js
import React from "react";
import Link from "next/link"
import Image from 'react-bootstrap/Image'
const BookComponent = (props) => {
return (
<>
<Link href={`/book/${props.book.id}`}>
<div className="book__wraper">
{props.book?.volumeInfo?.categories ?
<div className="book__category">{props.book?.volumeInfo?.categories[0]}</div>
: <></>}
{props.book?.volumeInfo?.imageLinks?.thumbnail ? (
<Image
src={props.book?.volumeInfo?.imageLinks?.thumbnail}
alt="book cover"
className="book__img"
/>
) : (
<Image className="noCover" src="https://rublevbar.com/files/rublevbar/image/no_product.jpg" alt="no book cover" />
)}
<div className="book__title">{props.book?.volumeInfo?.title}</div>
<div className="book__autors">{props.book?.volumeInfo?.authors}</div>
</div></Link>
</>
);
};
export default BookComponent;
pages/_app.js
import "../styles/globals.css";
import { store } from "../store";
import { Provider } from "react-redux";
import 'bootstrap/dist/css/bootstrap.min.css';
function MyApp({ Component, pageProps }) {
return (
<Provider store={store}>
<Component {...pageProps} />
</Provider>
);
}
export default MyApp;
pages/index.js
import React, { useEffect, useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { fetchBooksData } from "../slices/booksSlice";
import Head from "next/head";
import { Container, Form, Row, Col, Button, InputGroup } from "react-bootstrap";
import BookComponent from "../componets/BookComponent";
export default function Home() {
const books = useSelector((state) => state.books.books);
const name = useSelector((state) => state.books.name);
const startIndex = useSelector((state) => state.books.startIndex);
const error = useSelector((state) => state.books.error);
const [resultName, setResultName] = useState("book");
const [resultStartIndex, setResultStartIndex] = useState(0);
const [resultCategory, setResultCategory] = useState("all");
const [resultSort, setResultSort] = useState("relevance");
const dispatch = useDispatch();
useEffect(() => {
dispatch(
fetchBooksData({
name: resultName,
startIndex: resultStartIndex,
category: resultCategory,
sort: resultSort,
})
);
}, [resultName, resultStartIndex, resultCategory, resultSort, dispatch]);
if (error === "error") {
dispatch(
fetchBooksData({
name: resultName,
startIndex: resultStartIndex,
category: resultCategory,
sort: resultSort,
})
);
}
function categoryChange() {
setResultCategory(document.querySelector("#category").value);
setResultStartIndex(0);
dispatch(
fetchBooksData({
name: resultName,
startIndex: resultStartIndex,
category: resultCategory,
sort: resultSort,
})
);
}
function sortChange() {
setResultSort(document.querySelector("#sort").value);
setResultStartIndex(0);
dispatch(
fetchBooksData({
name: resultName,
startIndex: resultStartIndex,
category: resultCategory,
sort: resultSort,
})
);
}
function handleSubmit() {
const input = document.querySelector("#form");
setResultName(input.value);
}
function go_back() {
setResultStartIndex(resultStartIndex - 30);
}
function go_forward() {
setResultStartIndex(resultStartIndex + 30);
}
function handleKeyPress(e) {
if (e.charCode == 13) {
e.preventDefault()
const input = document.querySelector("#form");
setResultName(input.value);
}
}
return (
<>
<Head>
<title>Books catalog</title>
</Head>
<div id="page-preloader" className="preloader">
<div className="loader"></div>
</div>
<header className="header">
<Container>
<h1 className="title">Search for books</h1>
<Form>
<Row className="justify-content-center">
<Col xl={6}>
<InputGroup>
<Form.Control
onKeyPress={handleKeyPress}
id="form"
placeholder="Search books"
/>
<Button type="button" onClick={handleSubmit}>
Search
</Button>
</InputGroup>
</Col>
</Row>
<Row className="mt-3 justify-content-center">
<Col xl={3}>
<Form.Select
onChange={categoryChange}
id="category"
aria-label="Default select example"
>
<option value="all">all</option>
<option value="art">art</option>
<option value="biography">biography</option>
<option value="computers">computers</option>
<option value="history">history</option>
<option value="medical">medical</option>
<option value="poetry">poetry</option>
</Form.Select>
</Col>
<Col xl={3}>
<Form.Select
onChange={sortChange}
id="sort"
aria-label="Default select example"
>
<option value="relevance ">relevance </option>
<option value="newest">newest</option>
</Form.Select>
</Col>
</Row>
</Form>
</Container>
</header>
<Container>Всего книг по вашему запросу: {books.totalItems}</Container>
<Container>
<div className="books">
{books.items?.map((book, index) => {
return <BookComponent book={book} key={index} />;
})}
</div>
</Container>
<footer>
{resultStartIndex !== 0 ? (
<Button className="go_back" onClick={go_back}>
go back
</Button>
) : (
<></>
)}
{books.totalItems > resultStartIndex ? (
<Button className="go_forward" onClick={go_forward}>
go forward
</Button>
) : (
<></>
)}
</footer>
</>
);
}
pages/book/[id].js
import React, { useState, useEffect } from "react";
import Link from "next/link";
import { Button, Container, Image, Row, Col } from "react-bootstrap";
import { useSelector, useDispatch } from "react-redux";
import { fetchThisBookData } from "../../slices/thisBookSlice";
import { useRouter } from "next/router";
export default function bookId() {
const router = useRouter();
const book = useSelector((state) => state.thisBook.thisBook);
const error = useSelector((state) => state.thisBook.error);
const dispatch = useDispatch();
useEffect(() => {
dispatch(
fetchThisBookData({
id: router.query.id,
})
);
}, [dispatch, router]);
if (error === "error") {
dispatch(
fetchThisBookData({
id: router.query.id,
})
);
}
console.log(book);
return (
<div>
<Container>
<div id="page-preloader" className="preloader">
<div className="loader"></div>
</div>
<Link href={"/"} className="back">
<Button className="back">Back</Button>
</Link>
<Row className="justify-content-center">
<Col>
<h1 className="this_book__title">{book?.volumeInfo?.title}</h1>
</Col>
</Row>
<Row>
<Col xl={6}>
<strong>Категории:</strong>
{book?.volumeInfo?.categories ? (
<div className="this_book__category">
{book?.volumeInfo?.categories}
</div>
) : (
<div>Нет категорий</div>
)}
<div className="this_book__autors">
<strong>
{book?.volumeInfo?.authors.length === 1 ? (
<>Автор </>
) : (
<>Авторы: </>
)}
</strong>
{book?.volumeInfo?.authors}
</div>
<br />
</Col>
<Col xl={6}>
{book?.volumeInfo?.imageLinks?.extraLarge ? (
<Image
src={book?.volumeInfo?.imageLinks?.extraLarge}
alt="book cover"
className="this_book__img"
/>
) : (
<Image
className="noCover"
src="https://rublevbar.com/files/rublevbar/image/no_product.jpg"
alt="no book cover"
/>
)}
</Col>
</Row>
</Container>
</div>
);
}
slices/booksSlice.js
import { createSlice, createAsyncThunk } from "#reduxjs/toolkit";
const initialState = {
books: [],
status: null,
error: null,
};
export const fetchBooksData = createAsyncThunk(
"books/fetchData",
async function (state) {
const response = await fetch(
`https://www.googleapis.com/books/v1/volumes?q=${state.name}+${state.category}&startIndex=${state.startIndex}&maxResults=30&orderBy=${state.sort}`
);
const data = await response.json();
return data;
}
);
export const booksSlice = createSlice({
name: "books",
initialState,
extraReducers: {
[fetchBooksData.pending]: (state) => {
state.status = "loading";
state.error = null;
const preloader = document.querySelector("#page-preloader");
if (preloader.classList.contains("done")) {
preloader.classList.remove("done");
}
},
[fetchBooksData.fulfilled]: (state, action) => {
state.status = "resolved";
state.error = null;
state.books = action.payload;
const preloader = document.querySelector("#page-preloader");
if (!preloader.classList.contains("done")) {
preloader.classList.add("done");
}
},
[fetchBooksData.rejected]: (state) => {
state.error = "error";
console.log("Error");
},
},
});
export default booksSlice.reducer;
slices/thisBookSlice.js
import { createSlice, createAsyncThunk } from "#reduxjs/toolkit";
const initialState = {
thisBook: [],
status: null,
error: null,
};
export const fetchThisBookData = createAsyncThunk(
"books/fetchThisData",
async function (state) {
const response = await fetch(
`https://www.googleapis.com/books/v1/volumes/${state.id}`
);
const data = await response.json();
return data;
}
);
export const thisBookSlice = createSlice({
name: "book",
initialState,
extraReducers: {
[fetchThisBookData.pending]: (state) => {
state.status = "loading";
state.error = null;
const preloader = document.querySelector("#page-preloader");
if (preloader.classList.contains("done")) {
preloader.classList.remove("done");
}
},
[fetchThisBookData.fulfilled]: (state, action) => {
state.status = "resolved";
state.error = null;
state.thisBook = action.payload;
const preloader = document.querySelector("#page-preloader");
if (!preloader.classList.contains("done")) {
preloader.classList.add("done");
}
},
[fetchThisBookData.rejected]: (state) => {
state.error = "error";
console.log("Error");
},
},
});
export default thisBookSlice.reducer;

how to use material-ui Dialog PaperProps

I'm using v1.1.0 of material-ui in React 16.3.2. I'm trying to create a landing page similar to Showcase - Local Insights
where the dialog has opacity (Find foreclosures). I'm trying to use PaperProps for Dialog component described here Dialog doc
Here's a component I've created to try to do this.
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '#material-ui/core/styles';
import Button from '#material-ui/core/Button';
import Dialog from '#material-ui/core/Dialog';
import DialogActions from '#material-ui/core/DialogActions';
import DialogContent from '#material-ui/core/DialogContent';
import DialogTitle from '#material-ui/core/DialogTitle';
import ForwardIcon from '#material-ui/icons/Forward';
import Input from '#material-ui/core/Input';
import FormControl from '#material-ui/core/FormControl';
import Slide from '#material-ui/core/Slide';
const styles = theme => ({
dialogPaper: {
opacity: 0.5,
border: '#FF0000 1px solid',
},
button: {
margin: '30px'
}
});
function Transition(props) {
return <Slide direction="up" {...props} />;
}
class SignInDialog extends React.Component {
state = {
open: false,
username: ''
};
handleClickOpen = () => {
this.setState({ open: true });
};
handleClose = () => {
this.setState({ open: false });
};
handleChange = name => event => {
this.setState({
[name]: event.target.value,
});
};
render() {
const { classes } = this.props;
return (
<div>
<Button variant="fab" color="primary" aria-label="add" className={classes.button} onClick={this.handleClickOpen}>
<ForwardIcon />
</Button>
<Dialog
PaperProps={styles.dialogPaper}
open={this.state.open}
TransitionComponent={Transition}
onClose={this.handleClose}
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">WELCOME</DialogTitle>
<DialogContent>
<p>SIGN IN</p>
<FormControl className={classes.formControl}>
<Input
value={this.state.searchString}
onChange={this.handleChange('search')}
id="siginin-input"
placeholder="Enter your username"
/>
</FormControl>
</DialogContent>
<DialogActions>
<Button onClick={this.handleClose} color="primary">
Cancel
</Button>
<Button onClick={this.handleClose} color="primary">
Continue
</Button>
</DialogActions>
</Dialog>
</div>
);
}
}
SignInDialog.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(SignInDialog);
I haven't been able to figure out how to get the Dialog to take the styles. What is needed to get PaperProps to work?
If you want to use PaperProps you have to specify the props of the Paperfor which you are applying style.
<Dialog
PaperProps={{ classes: {root: classes.dialogPaper } }}
/>
You can also use classes property and override the style
<Dialog
classes={{paper:classes.dialogPaper}}
/>
The correct way to overide paper props is by using classNames
<Dialog
PaperProps={{ className: classNames(classes.dialogPaper) }}/>
<Dialog
PaperProps={{ classes: {root: classes.dialogPaper } }}
/>

How can I override the user-select: none in RadioButton and CheckBox control labels?

Currently for pre 1.0.0 releases Material-UI does not allow text selection on RadioButton and Checkbox control labels.
How can I override this behavior? Apparently passing labelStyle={{ userSelect: 'all' }} to the component doesn't help.
What I'm trying to achieve is being able to highlight the text in the option label as per this screenshot:
You need to override the CSS class that prevents selection of the labels.
The labels are made with components of type FormControlLabel. At the bottom of the doc page for that component, you can see that the CSS label class is available to override.
So, you need to override the label class on each FormControlLabel like this:
// Define the overriding style
const styles = () => ({
selectableLabel: {
userSelect: 'all',
},
});
// Override the label CSS that prevents selection
<FormControlLabel classes={{ label: classes.selectableLabel }} value="male" control={<Radio />} label="Male" />
Here's full code for a group of selectable radio buttons (derived from the Radio buttons example in the docs:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';
import Radio, { RadioGroup } from 'material-ui/Radio';
import { FormLabel, FormControl, FormControlLabel } from 'material-ui/Form';
const styles = theme => ({
root: {
display: 'flex',
},
formControl: {
margin: theme.spacing.unit * 3,
},
group: {
margin: `${theme.spacing.unit}px 0`,
},
selectableLabel: {
userSelect: 'all',
},
});
class RadioButtonsGroup extends React.Component {
state = {
value: '',
};
handleChange = (event, value) => {
this.setState({ value });
};
render() {
const { classes } = this.props;
return (
<div className={classes.root}>
<FormControl component="fieldset" required className={classes.formControl}>
<FormLabel component="legend">Gender</FormLabel>
<RadioGroup
aria-label="gender"
name="gender1"
className={classes.group}
value={this.state.value}
onChange={this.handleChange}
>
<FormControlLabel classes={{ label: classes.selectableLabel }} value="male" control={<Radio />} label="Male" />
<FormControlLabel classes={{ label: classes.selectableLabel }} value="female" control={<Radio />} label="Female" />
<FormControlLabel classes={{ label: classes.selectableLabel }} value="other" control={<Radio />} label="Other" />
<FormControlLabel classes={{ label: classes.selectableLabel }} value="disabled" disabled control={<Radio />} label="Disabled" />
</RadioGroup>
</FormControl>
</div>
);
}
}
RadioButtonsGroup.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(RadioButtonsGroup);
And here's the full code for the Checkbox buttons (derived from the Checkboxes example in the doc):
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';
import { FormControl, FormGroup, FormControlLabel } from 'material-ui/Form';
import Checkbox from 'material-ui/Checkbox';
const styles = {
selectableLabel: {
userSelect: 'all',
},
};
class CheckboxesGroup extends React.Component {
state = {
gilad: true,
jason: false,
antoine: true,
};
handleChange = name => (event, checked) => {
this.setState({ [name]: checked });
};
render() {
const { classes } = this.props;
return (
<FormControl component="fieldset">
<FormGroup>
<FormControlLabel
classes={{ label: classes.selectableLabel }}
control={
<Checkbox
checked={this.state.gilad}
onChange={this.handleChange('gilad')}
value="gilad"
/>
}
label="Gilad Gray"
/>
<FormControlLabel
classes={{ label: classes.selectableLabel }}
control={
<Checkbox
checked={this.state.jason}
onChange={this.handleChange('jason')}
value="jason"
/>
}
label="Jason Killian"
/>
</FormGroup>
</FormControl>
);
}
}
CheckboxesGroup.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(CheckboxesGroup);

How to create a new DraftInlineStyle?

I have tried to create a new state with Modifier.insertText and the third argument is supposed to a draftInlineStyle
let ncs = Modifier.insertText(contentStates, selections, superscriptVar, ["BOLD"]);
This does give bold but when i try to change the style later on it doesn't change. I have figured out this is because draftInlineStyle is supposed to be a constructor. So how do I create a draftInlineStyle constructor if i am supposed to pass a draftInlineStyle constructor? or is there any other way to do this?
You should use OrderedSet.of from Immutable.js.
let ncs = Modifier.insertText(
contentStates,
selections,
superscriptVar,
OrderedSet.of('BOLD')
);
If you want to apply many styles, pass them as arguments: OrderedSet.of('BOLD', 'ITALIC')
Check the simplified demo in the hidden snippet below:
const {Editor, RichUtils, Modifier, SelectionState, EditorState} = Draft;
const { OrderedSet } = Immutable;
class Container extends React.Component {
constructor(props) {
super(props);
this.state = {
editorState: EditorState.createEmpty()
};
}
insertTextHandler = (nameOfCustomStyle) => {
const currentSelection = this.state.editorState.getSelection();
const currentContent = this.state.editorState.getCurrentContent();
if (!currentSelection.isCollapsed()) return;
const newContentState = Modifier.insertText(currentContent, currentSelection, 'INSERTED TEXT', OrderedSet.of('BOLD'));
const newEditorState = EditorState.push(
this.state.editorState,
newContentState,
'change-inline-style'
);
this._handleChange(newEditorState)
}
toggleBoldStyle = () => {
this._handleChange(
RichUtils.toggleInlineStyle(
this.state.editorState,
'BOLD'
)
);
}
_handleChange = (editorState) => {
this.setState({ editorState });
}
render() {
return (
<div>
<div className="container-root">
<Editor
placeholder="Type away :)"
editorState={this.state.editorState}
onChange={this._handleChange}
/>
</div>
<button onClick={() => this.insertTextHandler()}>
INSERT TEXT
</button>
<button onClick={() => this.toggleBoldStyle()}>
TOGGLE BOLD STYLE FOR SELECTED TEXT
</button>
</div>
);
}
}
ReactDOM.render(<Container />, document.getElementById('react-root'))
body {
font-family: Helvetica, sans-serif;
}
.public-DraftEditor-content {
border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.0/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/draft-js/0.7.0/Draft.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/draft-js/0.10.0/Draft.js"></script>
<div id="react-root"></div>

Angular2 - Get hold of dynamically created element

I am experimenting with dynamic element creation using Angular2 and I have the following code using Renderer:
Component
export class DesignerComponent {
#ViewChild('builder') builder:ElementRef;
renderer: Renderer;
constructor(private elementRef: ElementRef, private rend: Renderer)
{
this.renderer = rend;
}
ngAfterViewInit() {
}
addRow() {
this.renderer.createElement(this.builder.nativeElement,'div');
console.log(
`* ${this.builder.nativeElement.innerHTML}`);
}
}
HTML:
<div #builder class="row">
</div>
<a class="btn-floating btn-large waves-effect waves-light red" (click)="addRow()"><i class="material-icons">add</i></a>
The 'div' gets created successfully but my question is: how do I get hold of that 'div' created dynamically?
I'm trying to get its reference so I can also create children in it. For instance: this div is a row and then I'd like to add columns to it.
Thanks very much for the help!
Update 1
My original code is this one
Component:
import { Component, ViewChild, ElementRef, Renderer} from '#angular/core';
#Component({
selector: 'c3',
template: `<h2>c3</h2>`
})
export class C3 {
}
#Component({
moduleId: module.id,
selector: 'my-row',
templateUrl: 'row.component.html',
styles: [
`.row:hover {
border: 3px dashed #880e4f ;
}
`
]
})
export class RowComponent {
colIndex: number = 0;
colList: Object[] = [];
rowId: number;
addColumn() {
this.colList.splice(this.colIndex, 0, ColumnComponent);
this.colIndex++;
}
removeColumn(colIdx: number) {
this.colList.splice(colIdx, 1);
}
setRowId(rowId: number) {
this.rowId = rowId;
}
}
#Component({
moduleId: module.id,
selector: 'my-column',
templateUrl: 'column.component.html',
styles: [
`.col:hover {
border: 3px solid #304ffe;
}
`
]
})
export class ColumnComponent {
row: RowComponent;
constructor(row: RowComponent) {
this.row = row;
}
removeColumn(colIdx: number) {
this.row.colList.splice(colIdx, 1);
}
}
#Component({
moduleId: module.id,
selector: 'my-site-designer',
templateUrl: 'sitedesigner.component.html',
styles: [`
nav {
height: 0px;
}
.side-nav {
width: 250px;
margin-top: 63px;
}
li.active {
color: #FFFFFF;
background-color: #1A237E;
}
li.active > a {
color: #FFFFFF;
background-color: #1A237E;
}
li.active > a > i{
color: #FFFFFF;
background-color: #1A237E;
}
/*
li.active i {
color: #FFFFFF;
background-color: #1A237E;
}
*/
`],
//template: `<p> teste teste</p>`
})
export class SiteDesignerComponent {
#ViewChild('builder') builder:ElementRef;
elementIndex: number = 0;
colIndex: number = 0;
list: Object[] = [];
colList: Object[] = [];
ngAfterViewInit() {
}
addRow() {
this.list.splice(this.elementIndex, 0, RowComponent);
this.elementIndex++;
}
remove(idx: number) {
this.list.splice(idx, 1);
}
}
HTML for the SiteDesignerComponent
<div #builder class="row">
<div class="s1 teal lighten-2">
<p class="flow-text">teste do html builder</p>
<div *ngFor="let row of list; let idx = index" >
<p class="flow-text">Linha {{idx}}</p>
<dcl-wrapper [type]="row"></dcl-wrapper>
<a class="btn-floating btn-small waves-effect waves-light purple" (click)="remove(idx)"><i class="material-icons">remove</i></a>
</div>
</div>
</div>
<a class="btn-floating btn-large waves-effect waves-light red" (click)="addRow()"><i class="material-icons">add</i></a>
HTML for the RowComponent
<div #row class="row" id="{{rowId}}">
<div class="s12 teal lighten-2">
<p class="flow-text">adding a row </p>
</div>
<div id="colunas" *ngFor="let col of colList; let colIndex = index">
<dcl-wrapper [type]="col"></dcl-wrapper>
<!--a class="btn-floating btn-small waves-effect waves-light deep-orange lighten-3" (click)="removeColumn(colIndex)"><i class="material-icons">remove</i></a-->
</div>
<a class="btn-floating btn-small waves-effect waves-light waves-teal" (click)="addColumn()"><i class="material-icons">view_column</i></a>
</div>
HTML for the ColumnComponent
<div class="col s4 purple lighten-2">
<p class="flow-text">adicionando coluna ....</p>
<a class="btn-floating btn-small waves-effect waves-light deep-orange lighten-3" (click)="removeColumn(colIndex)"><i class="material-icons">remove</i></a>
</div>
If I add two rows: the first with one column and the second with three columns and then if I remove the first row, it keeps the wrong columns (created in the second row). I know there is something wrong in the way I'm working the object arrays but I still can't figure it out.
Thanks for the help!
Got it solved.
updated HTML for the RowCompnent:
<div #row class="row" id="{{rowId}}">
<div class="s12 teal lighten-2">
<p class="flow-text">adicionando linha no html builder</p>
</div>
<div id="colunas" *ngFor="let col of colList; let colIndex = index">
<dcl-wrapper [type]="col"></dcl-wrapper>
<!--a class="btn-floating btn-small waves-effect waves-light deep-orange lighten-3" (click)="removeColumn(colIndex)"><i class="material-icons">remove</i></a-->
</div>
<a class="btn-floating btn-small waves-effect waves-light purple" (click)="removeRow()"><i class="material-icons">remove</i></a>
<a class="btn-floating btn-small waves-effect waves-light waves-teal" (click)="addColumn()"><i class="material-icons">view_column</i></a>
</div>
Updated RowComponent
export class RowComponent {
colIndex: number = 0;
colList: Object[] = [];
rowId: number;
selfRef: ElementRef;
selfRend: Renderer;
constructor(selfRef: ElementRef, selfRend: Renderer) {
this.selfRef = selfRef;
this.selfRend = selfRend;
}
addColumn() {
this.colList.splice(this.colIndex, 0, ColumnComponent);
this.colIndex++;
}
removeColumn(colIdx: number) {
this.colList.splice(colIdx, 1);
}
removeRow() {
this.selfRef.nativeElement.remove();
}
}
Thank you all for the help!