I am new in React, Now I am trying to do sidebar and hide show collapse menu item.
here is function=>
collapsemetoggle(){
this.setState(state => ({ collapsemeopen: !state.collapsemeopen }));
}
<div className="list-group list-group-flush">
Dashboard
<a onClick={this.collapsemetoggle} data-toggle="collapse" className="list-group-item list-group-item-action bg-light">Collapase Me</a>
<Collapse isOpen={this.state.collapsemeopen}>
<div className="list-group list-group-flush">
Dashboard
</div>
</Collapse>
</div>
</div>
But why
'Collapse' is not defined react/jsx-no-undef
is shown? I just reference from here=>
React Transition
I am trying to achieve to get sidebar like =>
Sidebar
Other people use ul li for menu list and I am trying to do with collapse. Is it the correct way? If not, Plase let me know for some example.
import Collapse:
import {Collapse} from 'react-bootstrap'
use props in instead of isOpen
<Collapse in={this.state.open}>
<div id="example-collapse-text">
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus
terry richardson ad squid. Nihil anim keffiyeh helvetica, craft beer
labore wes anderson cred nesciunt sapiente ea proident.
</div>
</Collapse>
When using Bootstrap or any other UI framework, you need to import the component you're using. Put this on top of your file and it will automatically import it.
import Collapse from 'react-bootstrap/Collapse'
By the way, the isOpen prop is not a Collapse prop. You should use in
<Collapse in={this.state.collapsemeopen}>
Related
I'm working on a website with react that maps through an instructors table and displays the instructors' image, name, and bio. I'm trying to use the react-read-more-read-less component to initially show 300 characters then show a Read More link to display all the text. If I hard code the text in the component it works perfectly but when I try to pull the data in from the db, I get an error that children.substr is not a function.
Here is the code:
<ReactReadMoreReadLess
readMoreClassName="readMoreClassName"
charLimit={300}
readMoreText="Read More"
readLessText="Read Less"
>
{parse(inst.instructorBio)}
</ReactReadMoreReadLess>
If I just use {inst.instructorBio} it works find but displays the p tags p.
I even tried to write a toggleShow function and it worked but it expanded all the instructors bios and I wasn't able to figure out how to only expand the one clicked.
Pares is from a npm package I installed to render the data correctly without showing the p tags. The pagckage is html-react-parser.
First solution:
The error occurs because only text is expected as a child element. Only text has a substring (substr) feature.
My solution will require further refinement but may be a good start. Use replacement for paragraphs. Maybe this function is enough:
const convert = (html) => html.replace(/<p>/gi, "\n").replace(/<\/p>/gi, "");
In order to use \n we need to wrap the element in pre
return (
<pre>
<ReactReadMoreReadLess charLimit={5}>
{inst.instructorBio}
</ReactReadMoreReadLess>
</pre>
);
This solution preserves line breaks well, but for the rest you will have to work with styles to make lines behave like paragraphs.
For wrap text in pre:
pre {
white-space: pre-wrap; /* css-3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
}
Second solution for many paragraphs — own component:
The -webkit-line-clamp CSS property allows limiting of the contents of a block to the specified number of lines.
const Fragment = React.Fragment
const MoreLessText = ({children}) => {
const [more, setMore] = React.useState(false)
return(
<Fragment>
<div className={"text" + (more ? '' : ' less')} >
{children}
</div>
<span onClick={() => setMore(!more)}> {/* toggle state*/}
{ more ? 'Show Less' : 'Show More'}
</span>
</Fragment>
)
}
const App = () => {
return (
<table border="1">
<tbody>
<tr>
<td>
<MoreLessText>
<p>
1) Lorem ipsum dolor sit amet consectetur adipisicing elit. Labore fugiat cumque, aliquam minus repellat voluptates adipisci. Consectetur, voluptatem nam quasi alias minima, nihil tenetur odit, a atque deleniti maiores est?
</p>
</MoreLessText>
</td>
</tr>
<tr>
<td>
<MoreLessText>
<p>
2) Lorem ipsum dolor sit amet consectetur adipisicing elit. Labore fugiat cumque, aliquam minus repellat voluptates adipisci. Consectetur, voluptatem nam quasi alias minima, nihil tenetur odit, a atque deleniti maiores est?
</p>
</MoreLessText>
</td>
</tr>
</tbody>
</table>
)
}
ReactDOM.render(<App/>, document.getElementById("root"));
.text{
width: 300px;
}
.less {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
line-clamp: 1;
-webkit-box-orient: vertical;
}
<script src="https://unpkg.com/react#17/umd/react.development.js" crossorigin ></script>
<script src="https://unpkg.com/react-dom#17/umd/react-dom.development.js" crossorigin ></script>
<script src="https://unpkg.com/babel-standalone#6/babel.min.js"></script>
<div id="root">
I'm having issues when dynamically assigning text colors to some headings. I have a .map function that runs and outputs some divs with different heading colors. This is example of my code:
{nftInfo.map((nft, index) => (
<div
className="flex flex-col space-y-3 rounded-lg border-2 border-opacity-25 bg-white p-5 hover:bg-slate-50 dark:border-slate-500 dark:bg-gray-700"
key={index}
>
<div
className={`flex justify-center space-x-4 font-bold text-${nft.color}-600 dark:text-${nft.color}-400`}
>
<div className={`text-lg `}>
{nft.title} {nft.color} <--- This outputs the correct color
</div>
{nft.icon}
</div>
</div>
Example of JSON:
{
title: 'Dummy text 2',
description: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Maxime minima odit aspernatur aliquam deleniti in corporis omnis cupiditate optio, voluptatum quasi reiciendis dolor, nostrum nihil quaerat est, doloremque mollitia possimus.',
bottomText: 'Lorem ipsum dolor sit amet consectetur adipisicing',
buttonText: 'Generate contract',
icon: <CodeIcon className="mt-1 h-6 w-6" />,
color: 'pink'
}
Here you can see that I'm assigning text colors depending on the color I set in the JSON above.
text-${nft.color}-600 dark:text-${nft.color}-400
I can also see the string being correctly assigned in the developer tools DOM view, but when I check the CSS in the dev tools the style is not applied...
Also, if I manually add the class to the div the heading does get colored...
The CSS file generated by Tailwind will only include classes that it recognizes when it scans your code, which means that dynamically generated classes (e.g. text-${nft.color}-600) will not be included.
To ensure that your colors are added to the CSS, you could add safelist in tailwind.config.js that holds all of the color utility classes that you need (see https://tailwindcss.com/docs/content-configuration#safelisting-classes).
module.exports = {
...
safelist: [
'text-pink-600',
'dark:text-pink-400',
]
}
Another solution is to add the utility classes in an object in your component, so that they get picked up and added to the stylesheet when Tailwind parses your code. You can then look up the colors using your nft.color variable. For instance:
const colors = {
"pink": {
"light": "text-pink-600",
"dark": "dark:text-pink-400",
},
...
}
<div className={`${colors[nft.color].light} ${colors[nft.color].dark}`} />
I'm using the <Card> component from Semantic-UI-React. I have a group of cards displaying some random information. I have the extra prop defined which renders a button. My idea is to have this button, when clicked, toggle/expand a div to display more information. I have looked around and not been able to find much on how to achieve this.
I looked into <Accordion> from semantic ui as well, but have not been able to get it to play nicely nested inside the card component.
I created a sandbox to show what I have so far and the general look of what I explained above.
For brevity I will only post the code of one card out of the group below.
<Card color="blue">
<Card.Content header="Elliot" textAlign="center" />
<Card.Content description="'Elliot is a sound engineer living in Nashville who enjoys playing guitar and hanging with his cat.'" />
<Card.Content extra>
<Button basic circular icon size="tiny">
<Icon name="plus circle" />
</Button>
Show More
</Card.Content>
</Card>
I agree with #brandon-r that you can handle the extra content being show by handling a state object (in my case an array). What I did differently from his example was to take advantage of the <Card.Content extra> component, which handles all the styles issues.
To handle opening and closing the extra content, I used a simple reducer. I like to use the useReducer hook on those UI interactions that need a more complex state handling. Then I created three components: one that shows the extra content when opened, another that shows the button to display the content, and a third one that toggles between the two. I did it this way to be able to generalise it in the future.
Anyways, here is the link to my forked CodeSandbox with my take on the solution:
https://codesandbox.io/embed/semantic-ui-card-extra-content-toggle-kybt2
I hope it helps
Edit #1
Added style={{height: "100%"}} to the card so they mantain their size when one of the cards is opened.
Edit #2
Add picture showing a card with a long description.
<Card color="blue" style={{ height: "100%" }}>
<Card.Content header="Elliot" textAlign="center" />
<Card.Content description="'Elliot is a sound engineer living in Nashville who enjoys playing guitar and hanging with his cat.'" />
<ExtraContentAccordion
content="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis ac commodo diam, et tincidunt massa. Sed aliquet tortor purus, in pulvinar enim mattis ac. Maecenas vestibulum cursus lorem, quis fermentum enim lacinia a. Ut nec feugiat nisl. Morbi finibus hendrerit diam, id iaculis nibh feugiat sed. Sed non justo turpis. Fusce neque quam, facilisis eu aliquam vitae, hendrerit nec nulla. Integer metus sapien, dictum eget viverra et, dictum in lectus. Integer vitae dolor ut libero dictum tristique eget non nunc. Suspendisse diam urna, pretium sed elementum sed, fermentum eu leo. Donec augue tortor, rhoncus id pulvinar ac, fringilla eu est. Duis et ante tristique dui molestie maximus at ut enim. Curabitur facilisis tempor lorem quis scelerisque. Maecenas enim leo, mollis at egestas in, vulputate eget risus."
onToggle={toggleCard(1)}
open={state[1]}
/>
</Card>
If you want to expand to show more content, you can keep track of which cards are expanded with some react state. In the UI, you can use the state to determine if you should render the extra content for a particular card.
EX:
import React, { useState } from "react";
import ReactDOM from "react-dom";
import { Card, Button, Icon } from "semantic-ui-react";
import "./styles.css";
function App() {
const [expanded, setExpanded] = useState({});
const cards = [1, 2, 3, 4, 5, 6];
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<Card.Group itemsPerRow={3}>
{cards.map(cardNumber => (
<Card color="blue">
<Card.Content header="Elliot" textAlign="center" />
<Card.Content description="'Elliot is a sound engineer living in Nashville who enjoys playing guitar and hanging with his cat.'" />
<Card.Content extra>
<Button
basic
circular
icon
size="tiny"
onClick={() =>
setExpanded({
...expanded,
[cardNumber]: !expanded[cardNumber]
})
}
>
<Icon name="plus circle" />
</Button>
{expanded[cardNumber] && (
<div style={{ height: 200 }}>
Extra content expanded for card {cardNumber}
</div>
)}
Show More
</Card.Content>
</Card>
))}
</Card.Group>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Here is a short sandbox to see what it looks like: https://codesandbox.io/s/modest-mayer-t12ot
This is probably an easy answer, but I am having difficulty wrapping my brain around it. I am building an Angular dashboard and once logged in, users can browser to /dashboard; I also have nested states for browsing around the dashboard. Below is how my states are setup (shortened for brevity)
app.js
.state('dashboard', {
url: '/dashboard',
templateUrl: 'views/dashboard.html'
})
.state('dashboard.new', {
url: '/new',
templateUrl: 'views/dashboard.new.html'
});
dashboard.html
<div page-header></div>
<div dashboard-menu></div>
<section>
<div class="container mt48">
<div class="row">
<div class="col-sm-12 text-center">
<h4 class="uppercase mb16">This is the dashboard default page</h4>
<p class="lead mb64">
FSed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut
odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.
</p>
</div>
</div>
</div>
</div>
</section>
<div ui-view></div>
Although not pertaining to this question, I've created two directives for the page-header and dashboard-menu (just in case you wondered what that was)
browser view: (Edited to add another screenshot of entire header)
What I would like to know how to do is when an active state is activated - in this example, dashboard/new that the default content on the /dashboard page will not be shown.
Thank you for taking a look - please ask me anything as I know what I was trying to ask and am hopeful I did without being confusing. Thank you.
The quickest way I think would be to hide the default text with ng-show. State can be determined by the $state object. Alternatively, perhaps it can be injected through the resolve function of the route itself.
How would i go about using Bootstrap's Scrollspy when I am using Backbone.js hash based routing?
Backbone router example, which creates page www.example.com/#somePage/123
var AppRouter = Backbone.Router.extend({
routes: {
"": "home",
"somePage/:id": "somePage"
},
somePage: function (id) {
console.log("do something");
}
});
$(document).ready(function(){
window.app = new AppRouter();
Backbone.history.start();
});
Twitter scrollSpy example which should append #anchor-value to the end the URL:
<div id="navbar" class="row-fluid">
<ul class="nav nav-pills navbar">
<li class="active">
1
</li>
<li>
2
</li>
</ul>
</div>
<div data-spy="scroll" data-target=".navbar">
<h4 id="step1">Step 1</h4>
<p>Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.</p>
<h4 id="step2">Step 2</h4>
<p>Veniam marfa mustache skateboard, adipisicing fugiat velit pitchfork beard. Freegan beard aliqua cupidatat mcsweeney's vero. Cupidatat four loko nisi, ea helvetica nulla carles. Tattooed cosby sweater food truck, mcsweeney's quis non freegan vinyl. Lo-fi wes anderson +1 sartorial. Carles non aesthetic exercitation quis gentrify. Brooklyn adipisicing craft beer vice keytar deserunt.</p>
</div>
This wants to turn the URL to something like www.example.com/#somePage/123#step1, which is not working.
Here is a possible solution using the Bootstrap demo Scrollspy: https://jsfiddle.net/8wvdpddq/
Assuming you wish to have the URL updated and a history point added as the user scrolls, the following code should achieve it:
$('body').on('activate.bs.scrollspy', function () {
var active = $('nav li:not(.dropdown).active a').attr('href').slice(1);
window.app.navigate(active, {trigger: true});
console.log('update url/history to ' + active);
})
In this case, trigger is also set, meaning your routing handlers will fire, if you don't want this, just remove this option.