I have a toggle to show/hide a specific DIV and change the button text based on the current React Hook State. When I view the console log, every single time I click it re-renders the complete page again in Next.js. Not 100% sure if this is normal, But I don't think this should happen if you only toggle one element.
useEffect you can pass property to say whether a specific state is changed or not.
Is there a smarter way of toggling an element and changing its text on click? Without having to re-render the complete code but only the part that you are working with.
import { useEffect, useState } from "react";
import { NextPage } from "next";
import Head from "next/head";
import Link from "next/link";
import HeroModule from "#modules/HeroModule";
import VideoModule from "#modules/VideoModule";
import ImageModule from "#modules/ImageModule";
import SliderModule from "#modules/SliderModule";
import QuoteModule from "#modules/QuoteModule";
import PreFooterModule from "#modules/PreFooterModule";
import Footer from "#components/Footer";
import Comments from "#components/Comments";
const Article: NextPage = () => {
const btnClass = "bg-transparent";
const text = "Reactie plaatsen";
const [buttonActive, setButtonActive] = useState(btnClass);
const [buttonText, setButtonText] = useState(text);
const [openForm, setOpenForm] = useState(false);
const onToggleForm = () => {
setOpenForm(!openForm);
if (!openForm) {
setButtonText("Sluiten");
setButtonActive("bg-navyBlue text-white");
} else {
setButtonActive("bg-transparent text-navyBlue");
setButtonText(text);
}
};
return (
<>
<Head>
<title>Artikel Detail</title>
<meta name="author" content="" />
<meta name="description" content="Developed by Friends For Brands" />
<link rel="icon" href="/favicon.ico" />
</Head>
<HeroModule
title="De headline van deze tekstuele content"
text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
/>
<div className="max-w-screen-xl px-6 pt-16 pb-12 mx-auto border-b-2 border-gray-300 lg:px-8 text-navyBlue ">
<div className="grid w-full grid-cols-12 gap-6">
<aside className=" lg:col-span-3 col-span-full">
<div className="grid grid-cols-12 lg:sticky lg:top-5 lg:block">
<div className="col-span-2 mb-4 avatar">
<div className="w-16 h-16 sm:h-20 sm:w-20 md:w-24 md:h-24 rounded-full ring ring-[#65c3c8] ring-offset-base-100 ring-offset-2">
<img src="https://i.pravatar.cc/300" alt="" />
</div>
</div>
<div className="col-span-8 leading-2">
<p className="font-bold">John Doe</p>
<p>Marketing Manager</p>
<p className="mt-2 md:mt-6">00/00/0000</p>
<p>Leestijd 10 minuten</p>
<div className="mt-6 card-actions">
<Link href="/tag/fashion" passHref>
<span className="text-[11px] font-semibold uppercase cursor-pointer badge badge-outline hover:bg-navyBlue hover:text-white">
Fashion
</span>
</Link>
<Link href="/tag/products" passHref>
<span className="text-[11px] font-semibold uppercase cursor-pointer badge badge-outline hover:bg-navyBlue hover:text-white">
Products
</span>
</Link>
</div>
</div>
</div>
</aside>
<main className="leading-relaxed col-span-full lg:col-span-9 md:text-normal">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.
</p>
<h2 className="mt-3 text-3xl md:text-4xl">Heading 2</h2>
<h3 className="mt-3 text-2xl md:text-3xl">Heading 3</h3>
<h4 className="mt-3 text-xl md:text-2xl">Heading 4</h4>
<ul className="pl-6 my-4 list-disc">
<li>Lorem ipsum dolor sit amet</li>
<li>
Consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
labore
</li>
<li>Et dolore magna aliqua. Ut enim ad minim veniam</li>
<li>
Quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat.
</li>
</ul>
<h2 className="mt-6 text-3xl md:text-4xl">H2: Tussentitel</h2>
<ul className="pl-6 my-4 list-decimal">
<li>Lorem ipsum dolor sit amet</li>
<li>
Consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
labore
</li>
<li>Et dolore magna aliqua. Ut enim ad minim veniam</li>
<li>
Quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat.
</li>
</ul>
<h5 className="font-bold">Tussentitel paragraaf</h5>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.
</p>
<h3 className="mt-6 text-2xl md:text-3xl">H3: Video Module</h3>
<VideoModule id="mkggXE5e2yk" platform="youtube" />
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.
</p>
<h3 className="mt-6 text-2xl md:text-3xl">H3: Image Module</h3>
<ImageModule
url="https://images.pexels.com/photos/1193743/pexels-photo-1193743.jpeg"
caption="Photo of multicolored abstract painting"
alt="A Pexels image"
/>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.
</p>
<h3 className="mt-6 text-2xl md:text-3xl">H3: Slider Module</h3>
<SliderModule />
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.
</p>
<h3 className="mt-6 text-2xl md:h2text-3xl">H3: Quote Module</h3>
<QuoteModule />
</main>
</div>
</div>
<div className="w-full max-w-4xl px-4 py-20 mx-auto">
<div className="flex gap-4">
<h2 className="text-4xl">Comment Module</h2>
<button
onClick={onToggleForm}
className={`items-center justify-center px-4 py-2 text-xs font-medium uppercase transition duration-150 ease-in-out ${buttonActive} border rounded-full shadow-sm cursor-pointer border-navyBlue place-self-start sm:mt-0 hover:border-transparent hover:bg-navyBlue hover:text-white`}
>
{buttonText}
</button>
</div>
{openForm && <p>OPEN</p>}
</div>
{/* <Comments isOpen={openForm} toggleForm={onToggleForm} /> */}
<PreFooterModule />
<Footer />
</>
);
};
export default Article;
You can wrap onToggleForm in useCallback to memoize it. Then that function won't be recreated with every render. Also, be aware that using react strict mode will purposely double render to help you catch any side effects (a good thing and only happens in debug). So you can temporarily remove the <React.StrictMode> tags and see if your console.logs() stop doubling up.
Related
I recently started working with Framer Motion. I really like it, and it makes it a lot easier to animate divs and add page transitions. I am having a problem where I am checking if my form is toggled (open/closed) to animate that parent <form> tag using Framer Motion. <motion.form> However, I am already inside the check if the Toggle is active and this way it's firing and checking for two things the animation and toggle state.
How can I simply animate the form if toggleForm is active?
Parent Article.tsx:
import React, { useState, useCallback } from "react";
import { NextPage } from "next";
import Head from "next/head";
import Link from "next/link";
import VideoModule from "#modules/VideoModule";
import HeroModule from "#modules/HeroModule";
import SliderModule from "#modules/SliderModule";
import ImageModule from "#modules/ImageModule";
import QuoteModule from "#modules/QuoteModule";
import PreFooterModule from "#modules/PreFooterModule";
import Footer from "#components/Footer";
import CommentForm from "#components/CommentForm";
const Article: NextPage = () => {
const closeFormText = "Ik reageer later";
const respondFormText = "Ik wil reageren";
const [buttonText, setButtonText] = useState(respondFormText);
const [toggleForm, setToggleForm] = useState(false);
const onToggleForm = useCallback(() => {
setToggleForm(!toggleForm);
!toggleForm ? setButtonText(closeFormText) : setButtonText(respondFormText);
}, [toggleForm, setToggleForm]);
return (
<>
<Head>
<title>Artikel Detail</title>
<meta name="author" content="" />
<meta name="description" content="Developed by Friends For Brands" />
<link rel="icon" href="/favicon.ico" />
</Head>
<HeroModule
title="De headline van deze tekstuele content"
text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
/>
<div className="max-w-screen-xl px-6 pt-16 pb-12 mx-auto border-navyBlue border-b-1 lg:px-8 text-navyBlue ">
<div className="grid w-full grid-cols-12 gap-6">
<aside className=" lg:col-span-3 col-span-full">
<div className="grid grid-cols-12 lg:sticky lg:top-5 lg:block">
<div className="col-span-2 mb-4 avatar">
<div className="w-16 h-16 sm:h-20 sm:w-20 md:w-24 md:h-24 rounded-full ring ring-[#65c3c8] ring-offset-base-100 ring-offset-2">
<img src="https://i.pravatar.cc/300" alt="" />
</div>
</div>
<div className="col-span-8 leading-2">
<p className="font-bold">John Doe</p>
<p>Marketing Manager</p>
<p className="mt-2 md:mt-6">00/00/0000</p>
<p>Leestijd 10 minuten</p>
<div className="mt-6 card-actions">
<Link href="/tag/fashion" passHref>
<span className="text-[11px] font-semibold uppercase cursor-pointer badge badge-outline hover:bg-navyBlue hover:text-white">
Fashion
</span>
</Link>
<Link href="/tag/products" passHref>
<span className="text-[11px] font-semibold uppercase cursor-pointer badge badge-outline hover:bg-navyBlue hover:text-white">
Products
</span>
</Link>
</div>
</div>
</div>
</aside>
<main className="leading-relaxed col-span-full lg:col-span-9 md:text-normal">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.
</p>
<h2 className="mt-3 text-3xl md:text-4xl">Koptekst H2</h2>
<h3 className="mt-3 text-2xl md:text-3xl">Koptekst H3</h3>
<h4 className="mt-3 text-xl md:text-2xl">Koptekst H4</h4>
<ul className="pl-6 my-4 list-disc">
<li>Lorem ipsum dolor sit amet</li>
<li>
Consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
labore
</li>
<li>Et dolore magna aliqua. Ut enim ad minim veniam</li>
<li>
Quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat.
</li>
</ul>
<h2 className="mt-6 text-3xl md:text-4xl">Tussentitel</h2>
<ul className="pl-6 my-4 list-decimal">
<li>Lorem ipsum dolor sit amet</li>
<li>
Consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
labore
</li>
<li>Et dolore magna aliqua. Ut enim ad minim veniam</li>
<li>
Quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat.
</li>
</ul>
<h5 className="font-bold">Tussentitel paragraaf</h5>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.
</p>
<h3 className="mt-6 text-2xl md:text-3xl">Video Module</h3>
<React.StrictMode>
<VideoModule id="mkggXE5e2yk" platform="youtube" />
</React.StrictMode>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.
</p>
<h3 className="mt-6 text-2xl md:text-3xl">Image Module</h3>
<ImageModule
url="https://images.pexels.com/photos/1193743/pexels-photo-1193743.jpeg"
caption="Photo of multicolored abstract painting"
alt="A Pexels image"
/>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.
</p>
<h3 className="mt-6 text-2xl md:text-3xl">Slider Module</h3>
<SliderModule />
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.
</p>
<h3 className="mt-6 text-2xl md:h2text-3xl">Quote Module</h3>
<QuoteModule />
</main>
</div>
</div>
<CommentForm
buttonText={buttonText}
toggleForm={toggleForm}
clickHandle={onToggleForm}
/>
<PreFooterModule />
<Footer />
</>
);
};
export default Article;
Child component CommentForm.tsx:
import { motion } from "framer-motion";
const variants = {
open: { opacity: 1, x: 0 },
closed: { opacity: 0, x: "-100%" },
}
interface CommentFormProps {
buttonText: string;
toggleForm: boolean;
clickHandle: any;
}
const CommentForm = ({
buttonText,
toggleForm,
clickHandle,
}: CommentFormProps) => (
<div className="w-full max-w-4xl px-4 py-20 mx-auto">
<div className="flex gap-4">
<h2 className="text-2xl md:text-4xl">Reacties</h2>
<button
onClick={clickHandle}
className={`inline-flex px-4 py-2 place-items-center text-xs font-medium uppercase transition duration-150 ease-in-out border rounded-full cursor-pointer border-navyBlue hover:bg-navyBlue hover:text-white md:mt-1`}
>
{buttonText}
</button>
</div>
{toggleForm && (
<motion.form className="pt-8" autoComplete="off" animate {toggleForm ? "open" : "closed"}
variants={variants}>
<div className="grid xl:grid-cols-2 xl:gap-6">
<p className="mb-5 font-bold col-span-full md:m-0">Jouw gegevens</p>
<div className="relative z-0 w-full mb-6">
<input
type="text"
name="first_and_lastname"
id="first_and_lastname"
className="block w-full py-3 text-sm bg-transparent border-0 appearance-none text-navyBlue border-b-1 border-navyBlue focus:outline-none focus:ring-0 focus:border-bubblegum peer"
placeholder=" "
required
/>
<label
htmlFor="first_and_lastname"
className="absolute text-md text-navyBlue duration-200 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:left-0 peer-focus:text-navyBlue peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:uppercase peer-focus:scale-75 peer-focus:-translate-y-6"
>
Voor- en Acthernaam
</label>
</div>
<div className="relative z-0 w-full mb-6">
<input
type="email"
name="email"
className="block w-full py-3 text-sm bg-transparent border-0 appearance-none text-navyBlue border-b-1 border-navyBlue focus:outline-none focus:ring-0 focus:border-bubblegum peer"
placeholder=" "
required
/>
<label
htmlFor="email"
className="absolute text-md text-navyBlue duration-200 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:left-0 peer-focus:text-navyBlue peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:uppercase peer-focus:scale-75 peer-focus:-translate-y-6"
>
E-mailadres
</label>
</div>
</div>
<div className="relative z-0 w-full mt-2 mb-6">
<textarea
id="comment"
name="comment"
rows={5}
className="block w-full py-5 text-3xl bg-transparent border-0 appearance-none resize-none text-navyBlue border-b-1 border-navyBlue focus:outline-none focus:ring-0 focus:border-bubblegum peer"
placeholder=" "
required
/>
<label
htmlFor="comment"
className="absolute text-md text-navyBlue duration-200 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:left-0 peer-focus:text-navyBlue peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:uppercase peer-focus:scale-75 peer-focus:-translate-y-6"
>
Reactie
</label>
</div>
<button
type="submit"
className="items-center justify-center px-6 py-1.5 text-sm font-medium uppercase transition duration-150 ease-in-out bg-transparent border rounded-full shadow-sm md:text-lg text-navyBlue border-navyBlue hover:bg-navyBlue hover:text-white"
>
Reageer op artikel
</button>
</motion.form>
)}
</div>
);
export default CommentForm;
You're using the toggleForm state to change the animate property on the form, but you're also using it to conditionally render the form. So as soon as that state switches to false, the form is removed from the DOM, without having a chance to animate to the "closed" variant.
{toggleForm && (
<motion.form className="pt-8" autoComplete="off" animate {toggleForm ? "open" : "closed"}
variants={variants}>
//...etc
)}
The easiest fix would be remove the conditional rendering, and just use the state to change the animation variant on the motion.form element ("open" or "closed").
If you need to actually remove the form from the DOM like that, you can use AnimatePresence with an exit animation (don't forget to give the form a unique key prop!) to have the the element perform an animation before getting removed from the DOM.
I am using React Hooks and have a dummy content array of comments which I am mapping through to display it. Now, I am directly mapping through that array, but I would like filter => map before returning the output.
The hook from main file:
const [articleComments, setArticleComments] = useState([
{
name: "John Doe",
publishedAt: "22.03.2022",
image: "https://i.pravatar.cc/300",
post: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
},
{
name: "Jane Doe",
publishedAt: "03.01.2022",
image: "https://i.pravatar.cc/301",
post: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
},
{
name: "Jack Doe",
publishedAt: "17.03.2022",
image: "https://i.pravatar.cc/302",
post: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
},
]);
Comments.tsx:
const Comments = () => (
<div className="w-full px-4 pb-16 pr-4 mx-auto mt-5 md:pt-2 md:max-w-4xl">
<div className="flex flex-col gap-8 leading-relaxed text-md text-navyBlue">
{articleComments.length > 0 &&
articleComments.map(({ image, name, publishedAt, post }: any) => (
<div key={name} className="grid grid-cols-12 gap-4">
<div className="col-span-2 md:col-span-1 avatar">
<div className="w-12 h-12 rounded-full ring ring-[#65c3c8] ring-offset-2">
<img src={image} alt="" />
</div>
</div>
<div className="relative md:-mt-2 col-span-full md:col-span-11">
<h4 className="font-bold">{name}</h4>
<time>{publishedAt}</time>
<p className="mt-2">{post}</p>
</div>
</div>
))}
</div>
</div>
);
export default Comments;
I have a problem using the bootstrap tabs in AngularJS.
<div class="tab-container">
<ul class="nav nav-tabs">
<li class="active">Home</li>
<li>Profile</li>
<li>Messages</li>
</ul>
<div class="tab-content">
<div class="tab-pane active cont" id="home">
<h3 class="hthin">Basic Tabs</h3>
<p>This is an example of tabs </p>
</div>
<div class="tab-pane cont" id="profile">
<h2>Typography</h2>
<p>This is just an example of content
</div>
<div class="tab-pane" id="messages">..sdfsdfsfsdf.
</div>
</div>
</div>
The problem is that when I select a tab for example Home or Profile, I am redirected to /home or /profile url instead of showing the content of the tab itself.
I have a feeling that this can be somehow acheived with a directive and prevent the redirect to the page home or profile, instead show the tab content.
replace href with data-target.
<li class="active"><a data-target="#home" data-toggle="tab" >Home</a></li>
Directive can help you to handle it.
app.directive('showTab', function () {
return {
link: function (scope, element, attrs) {
element.click(function (e) {
e.preventDefault();
jQuery(element).tab('show');
});
}
};
});
<a show-tab href="#tab_1">
Tab 1
</a>
Source
You could try using the Angular UI bootstrap components located here, http://angular-ui.github.io/bootstrap/
this code will solve the problem while using Angularjs
<div class="tabbable tabs-below" ng-init="selectedTab = 1;">
<ul class="nav nav-tabs nav-justified">
<li ng-class="{active: selectedTab == 1}">
Personal
</li>
<li ng-class="{active: selectedTab == 2}">
Education
</li>
<li ng-class="{active: selectedTab == 3}">
Contact
</li>
</ul>
<div class="tab-content" ng-show="selectedTab == 1">
1. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
<div class="tab-content" ng-show="selectedTab == 2">
2. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
<div class="tab-content" ng-show="selectedTab == 3">
3. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
</div>
Use data-target instead of of href
<div class="page-menu-container">
<div class="container">
<div class="page-menu">
<ul class="nav nav-tabs">
<li><a data-toggle="tab" data-target="#Tab1">Tab1</a></li>
<li><a data-toggle="tab" data-target="#Tab2" >Tab2</a></li>
</ul>
</div>
</div>
</div>
<div class="tab-content">
<div id="Tab1" class="tab-pane fade in active"> Tab1 contant
</div>
<div id="Tab2" class="tab-pane fade in active"> Tab2 contant
</div>
</div>
I have created a simple ng-click function that hides and shows a DIV.
However, rather and simply appearing and disappearing, does angular have the ability to give a sliding effect?
Here's a plunkr: http://plnkr.co/edit/jbHidL3oOQvi4RBCkJIF?p=preview
HTML:
<div class="grid-wrap">
<div class="grid-col one-third">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
Show the slidy section
</div>
<div class="grid-col two-thirds" ng-show="showMe">
My hidden section that i want to slide out
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua</p>
<p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis irure dolor in repr</p>
</div>
</div>
You should have a good read about ng-animate (it have to be injected into your app - something a lot of ppl forget) then you can take a look here
http://www.nganimate.org/angularjs/ng-switch/slider-css3-transition-animation
a well designed examples of what ng-animate can do
Google CDN angularjs-animate.min.js
I have a set of headings (<h3>) that when clicked, they hide/show their corresponding sections.
I have achieved this by using ng-show/ng-hide and then calling a $scope variable isInactive/isActive.
What i would like to know, is if the same result can be achieved, without the need for using JS within $scope.isInactive and $scope.isActive and logic be placed in the HTML markup? Possibly with the us of ng-class?
HTML:
<div ng-app="">
<div ng-controller="EventController">
<div class="tabs">
<h3 class="" id="tab-{{$index}}-0"><a id="1" data="{{$index}}" ng-click="switch($event)">1 - 5 Years</a></h3>
<h3 class="inactive" id="tab-{{$index}}-1"><a id="2" data="{{$index}}" ng-click="switch($event)">6 - 10 Years</a></h3>
<h3 class="inactive" id="tab-{{$index}}-2"><a id="3" data="{{$index}}" ng-click="switch($event)">11 - 15 Years</a></h3>
<h3 class="inactive" id="tab-{{$index}}-3"><a id="4" data="{{$index}}" ng-click="switch($event)">16 - 20 Years</a></h3>
<div class="clear" data="{{$index}}" ng-hide="isInactive('#tab-'+{{$index}} + '-0')">1 - 5 Years Text - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris</div>
<br>
<div class="clear" ng-show="isActive('#tab-'+{{$index}} + '-1')">6 - 10 Years Text - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris</div>
<br>
<div class="clear" ng-show="isActive('#tab-'+{{$index}} + '-2')">11 - 15 Years Text - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris</div>
<br>
<div class="clear" ng-show="isActive('#tab-'+{{$index}} + '-3')">16 - 20 Years Text - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris</div>
</div>
</div>
</div>
JS:
function EventController($scope) {
$scope.
switch = function (e) {
var target = e.target || e.srcElement;
var elem = angular.element(target);
var parent = elem.parent();
var allHeadings = parent.parent().find("h3");
angular.forEach(allHeadings, function (aHeading) {
var child = angular.element(aHeading);
child.addClass("inactive");
});
parent.removeClass("inactive");
}
$scope.isInactive = function (e) {
var elem = angular.element(document.querySelector(e));
if (elem.hasClass("inactive")) {
return true;
} else {
return false;
}
};
$scope.isActive = function (e) {
var elem = angular.element(document.querySelector(e));
if (elem.hasClass("inactive")) {
return false;
} else {
return true;
}
};
}
My jsFiddle: http://jsfiddle.net/oampz/Wr79J/2/
Yes, you have correctly identified this the apt place for using ng-class.
It is possible to do only using HTML and a minimalistic controller: http://jsfiddle.net/Wr79J/4/
JS
function EventController($scope) {
$scope._activeTab = 1;
}
HTML
<div ng-app="">
<div ng-controller="EventController">
<div class="tabs">
<h3 ng-class="{ 'inactive': _activeTab !== 1, 'active': _activeTab == 1 }">
<a id="1" ng-click="_activeTab=1">1 - 5 Years</a></h3>
<!-- .... -->
<div class="clear" ng-show="_activeTab == 1">
1 - 5 Years Text - Lorem ipsum ...
</div>
</div>
Note: I think you were using {{$index}} from a scope this part of the template had inherited. I have left that untouched in the example.
Though this works, this code is not very maintainable. You may want to use more descriptive names for the tabs instead of 1, 2, 3, and 4.
You can get rid of the controller completely using an ng-init="_activeTabe = 1" on the container div, but it is not the correct use of ng-init.
Also, it is not considered good practise to manipulate the DOM in any way from the controller (I am looking at the addClass/removeClass in the code). If it is necessary, then one should use directives (e.g. ng-class) for the manipulation.
You can just set a variable to set the active tab.
<div class="tabs">
<h3 ng-click="range=1">1-5</h3>
<h3 ng-click="range=2">6-10</h3>
<div class="clear" ng-show="range==1">1 - 5 Years Text</div>
<div class="clear" ng-show="range==2">6 - 10 Years Text</div>
</div>
Here is an example - http://plnkr.co/edit/NTVPbOC5k7HKo88qp6vN?p=preview with no javascript code for the above logic.
<div>
<div>
<div class="tabs">
<h3 ng-init="active=1" ng-click="active=1" ng-class="{true:'active', false:'inactive'}[active==1]"><a >1 - 5 Years</a></h3>
<h3 ng-click="active=2" ng-class="{true:'active', false:'inactive'}[active==2]"><a >6 - 10 Years</a></h3>
<h3 ng-click="active=3" ng-class="{true:'active', false:'inactive'}[active==3]"><a >11 - 15 Years</a></h3>
<h3 ng-click="active=4" ng-class="{true:'active', false:'inactive'}[active==4]"><a >16 - 20 Years</a></h3>
<div ng-show="active==1">1 - 5 Years Text - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris</div>
<br>
<div ng-show="active==2">6 - 10 Years Text - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris</div>
<br>
<div ng-show="active==3">11 - 15 Years Text - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris</div>
<br>
<div ng-show="active==4">16 - 20 Years Text - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris</div>
</div>
</div>
</div>