i have a trouble at the moment will rendering html tag inside state. When i add 'div dangerouslySetInnerHTML={{__html: this.state.actions}} it seems can't because i will render in li tag for menu
this.state = {
sideBar : '<li>[object Object]</li>'
}
// when i render
render(){
return(
{ this.state.sideBar}
) ==> // '<li>[object Object]</li>'
// what should happen is to create a new list
[object Object]
You can get it working without using dangerouslySetInnerHTML. Here's an example of using <ul> and an array of <li> tags that you can render directly in React.
class App extends Component {
constructor(props) {
super(props);
this.state = {
list: ["list 1", "list 2", "list 3"]
};
}
render() {
return (
<div>
<ul>
{this.state.list.map((obj, index) => <li key={index}>{obj}</li> )}
</ul>
</div>
);
}
}
like this code
import React, { Component } from 'react'
import { Route, NavLink, Link } from 'react-router-dom'
import ReactTimeout from 'react-timeout'
class Menu extends Component {
constructor() {
super();
this.state = {
menuBar: [],
sideBar: []
}
}
async componentDidMount() {
const res = await fetch('http://localhost:3001/api/menu/' + 18)
const something = await res.json()
this.setState({ menuBar: something })
console.log(this.state.menuBar)
let menuBar = this.state.menuBar
let html = "";
let link_menu = []
for (var i = 0; i < menuBar.length; i++) {
if (menuBar.menu_url == 'dashboard' || menuBar.menu_flag_link === 1) {
var span_selected = ''
} else {
var span_selected = 'arrow'
}
if (menuBar.menu_flag_link == 0) {
var title_menu = menuBar[i].menu_title
link_menu =
<NavLink
to='javascript:;'
exact>title_menu</NavLink>
} else {
var title_menu = menuBar[i].menu_title
link_menu = <NavLink
to="/"
exact>title_menu</NavLink>
}
html += '<li>' + link_menu
if (menuBar[i].child.length > 0) {
html += "<ul class='sub-menu'>"
for (var j = 0; j < menuBar[i].child.length; j++) {
if (menuBar[j].child.menu_flag_link == 0) {
var link_menu2 = <NavLink
to='javascript:;'
exact>menuBar.child.menu_title</NavLink>
} else {
var link_menu2 =
<NavLink
to="/"
exact>menuBar.child.menu_title</NavLink>
}
html += "<li>, ${link_menu2}"
if (menuBar[i].child[j].length > 0) {
html += "<ul class='sub-menu'>"
for (var kjh = 0; kjh < menuBar[i].child[j].length; kjh++) {
var link_menu3 =
<NavLink
to="/"
exact>menuBar.child.menu_title</NavLink>
html += '<li> ${link_menu3} </li>'
}
html += '</ul>'
}
html += '</li>'
}
html += '</ul>'
}
html += '</li>'
}
this.setState({ sideBar: html })
}
render() {
let menuBar = this.state.menuBar
let sideBar = this.state.sideBar
// console.log(sideBar)
return (
<div class="page-sidebar-wrapper">
<div class="page-sidebar navbar-collapse collapse">
<ul class="page-sidebar-menu page-sidebar-menu-light" data-keep-expanded="true" data-auto-scroll="true" data-slide-speed="200">
<li class="sidebar-toggler-wrapper">
<div class="sidebar-toggler">
</div>
</li>
<li class="sidebar-search-wrapper">
<form class="sidebar-search " action="extra_search.html" method="POST">
<a href="javascript:;" class="remove">
<i class="icon-close"></i>
</a>
<div class="input-group">
<input type="text" class="form-control" placeholder="Search..." />
<span class="input-group-btn">
<i class="icon-magnifier"></i>
</span>
</div>
</form>
</li>
<li class="start active open">
<a href="javascript:;">
<i class="icon-home"></i>
<span class="title">Dashboard</span>
<span class="selected"></span>
<span class="arrow open"></span>
</a>
<ul class="sub-menu">
<li>
<NavLink
to="/"
exact>Home</NavLink>
</li>
<li class="active">
<NavLink to={{
pathname: '/blog',
hash: '#submit',
search: '?quick-submit=true'
}}
>Blog</NavLink>
</li>
<li>
<NavLink to={{
pathname: '/Table'
}}>Table</NavLink>
</li>
<li>
<NavLink to={{
pathname: '/BCC'
}}>BCC</NavLink>
</li>
</ul>
</li>
{this.state.sideBar}
<li>
<a href="javascript:;">
<i class="icon-folder"></i>
<span class="title">Multi Level Menu</span>
<span class="arrow "></span>
</a>
<ul class="sub-menu">
<li>
<a href="javascript:;">
<i class="icon-settings"></i> Item 1 <span class="arrow"></span>
</a>
<ul class="sub-menu">
<li>
<a href="javascript:;">
<i class="icon-user"></i>
Sample Link 1 <span class="arrow"></span>
</a>
<ul class="sub-menu">
<li>
<i class="icon-power"></i> Sample Link 1
</li>
<li>
<i class="icon-paper-plane"></i> Sample Link 1
</li>
<li>
<i class="icon-star"></i> Sample Link 1
</li>
</ul>
</li>
<li>
<i class="icon-camera"></i> Sample Link 1
</li>
<li>
<i class="icon-link"></i> Sample Link 2
</li>
<li>
<i class="icon-pointer"></i> Sample Link 3
</li>
</ul>
</li>
<li>
<a href="javascript:;">
<i class="icon-globe"></i> Item 2 <span class="arrow"></span>
</a>
<ul class="sub-menu">
<li>
<i class="icon-tag"></i> Sample Link 1
</li>
<li>
<i class="icon-pencil"></i> Sample Link 1
</li>
<li>
<i class="icon-graph"></i> Sample Link 1
</li>
</ul>
</li>
<li>
<a href="#">
<i class="icon-bar-chart"></i>
Item 3 </a>
</li>
</ul>
</li>
</ul>
</div>
</div>
)
}
}
export default ReactTimeout(Menu)
Related
I have been staring at this code for far too long, unfortunately I do not see the problem.
I am trying to get the active menu entry highlighted when the relevant div gets scrolled into view. But nothing is happening and no errors are being thrown in the console.
My menu html:
<section class="LeftAnchorNav" style="display: block;">
<nav id="LeftAnchorNav">
<div class="container" style="padding-left: 50px;">
<div class="col-md-4 LeftAnchorNavWrapper">
<ul class="LeftAnchorNavMenu">
<li class="leftanchorlink">
<a class="leftlink" href="#20a51af3-f8b0-4ef9-ba73-cf3cd0a321b9">About us</a>
</li>
<li class="leftanchorlink">
<a class="leftlink" href="#d736bc13-a2a7-48d4-8ecc-75b9a17f801b">Demo Center</a>
</li>
<li class="leftanchorlink">
<a class="leftlink" href="#545a6339-87e4-41ed-ad51-70c3788cedee">Testimonial</a>
</li>
<li class="leftanchorlink">
<a class="leftlink" href="#9355324a-6219-4300-ae97-aa77bf67dab4">Newsletter</a>
</li>
<li class="leftanchorlink">
<a class="leftlink" href="#0c70b0db-3e70-4faa-ab98-154b4eae498e">Blog</a>
</li>
<li class="leftanchorlink">
<a class="leftlink" href="#4903bc53-b862-42f0-a600-e21061204e42">Contact</a>
</li>
<li class="leftanchorlink">
<a class="leftlink" href="#002f6fd7-758b-4b27-8c75-0ce087ee826a">Solution Finder</a>
</li>
</ul>
</div>
</div>
</nav>
</section>
An example div:
<div class="block anchorblock col-lg-12 col-md-12 col-sm-12 col-xs-12 span12 "><div id="20a51af3-f8b0-4ef9-ba73-cf3cd0a321b9"></div>
</div>
My jquery/js:
if ($('.LeftAnchorNav').length > 0) {
// prepare the variables
var lastID;
var anchorMenu = $(".LeftAnchorNavMenu");
var anchorMenuHeight = anchorMenu.outerHeight() + 100;
var anchorMenuItems = anchorMenu.find(".leftlink");
var anchorMenuItemsTarget = anchorMenuItems.map(function () {
var item = $($(this).attr("href"));
if (item.length) { return item; }
});
// bind everything to the scrolling
$(window).scroll(function () {
// get anchornav container scroll position and add buffer
var fromTop = $(this).scrollTop() + anchorMenuHeight + 300;
// get ID of the current scroll item
var currentItem = anchorMenuItemsTarget.map(function () {
if ($(this).offset().top < fromTop)
return this;
});
// get the ID of the current element
currentItem = currentItem[currentItem.length - 1];
var id = currentItem && currentItem.length ? currentItem[0].id : "";
if (lastID !== id) {
lastID = id;
// Set/remove active class
anchorMenuItems.removeClass("highlightleftnavactive")
anchorMenuItems.filter("[href='#" + id + "']").addClass("highlightleftnavactive");
}
});
}
It's quite fiddly to do the arithmetic for scrolling so this snippet uses IntersectionObserver instead. This has the added benefit of less processing overhead as it just gets informed when the elements come in or go out of view, not every time the user scrolls a bit.
It sets up the observer to observe when any of the relevant elements come into or go out of the viewport. When alerted to that it adds or removes the highlighting class to the related navbar link.
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script>
<style>
.LeftAnchorNav {
position: fixed;
z-index:1;
}
.tall {
width: 100vw;
height: 100vh;
background-image: linear-gradient(cyan, magenta, yellow, black);
}
.highlightleftnavactive {
background-color: yellow;
}
</style>
</head>
<section class="LeftAnchorNav" style="display: block;">
<nav id="LeftAnchorNav">
<div class="container" style="padding-left: 50px;">
<div class="col-md-4 LeftAnchorNavWrapper">
<ul class="LeftAnchorNavMenu">
<li class="leftanchorlink">
<a class="leftlink" href="#20a51af3-f8b0-4ef9-ba73-cf3cd0a321b9">About us</a>
</li>
<li class="leftanchorlink">
<a class="leftlink" href="#d736bc13-a2a7-48d4-8ecc-75b9a17f801b">Demo Center</a>
</li>
<li class="leftanchorlink">
<a class="leftlink" href="#545a6339-87e4-41ed-ad51-70c3788cedee">Testimonial</a>
</li>
<li class="leftanchorlink">
<a class="leftlink" href="#9355324a-6219-4300-ae97-aa77bf67dab4">Newsletter</a>
</li>
<li class="leftanchorlink">
<a class="leftlink" href="#0c70b0db-3e70-4faa-ab98-154b4eae498e">Blog</a>
</li>
<li class="leftanchorlink">
<a class="leftlink" href="#4903bc53-b862-42f0-a600-e21061204e42">Contact</a>
</li>
<li class="leftanchorlink">
<a class="leftlink" href="#002f6fd7-758b-4b27-8c75-0ce087ee826a">Solution Finder</a>
</li>
</ul>
</div>
</div>
</nav>
</section>
<div class="tall"></div>
<div class="block anchorblock col-lg-12 col-md-12 col-sm-12 col-xs-12 span12 "><div id="20a51af3-f8b0-4ef9-ba73-cf3cd0a321b9">
An example block coming into and going out of view it belongs to the About us link in the navbar</div>
</div>
<div class="tall"></div>
<script>
let callback = (entries) => {
entries.forEach(entry => {
let id = entry.target.firstChild.id;
let leftLink = document.querySelector("a.leftlink[href='#"+ id + "']");
if (entry.isIntersecting) { leftLink.classList.add('highlightleftnavactive');}
else { leftLink.classList.remove('highlightleftnavactive');}
});
};
const observer = new IntersectionObserver(callback);
const anchorBlocks = document.querySelectorAll('.anchorblock');
anchorBlocks.forEach( (anchorBlock) => {
observer.observe(anchorBlock);
});
</script>
I want to assign "active" class to the menu. The active clip is throwing but not deleting. I do not understand why you did not delete. Thank you in advance to those who can help.
There is no error, it surprises me that it does not delete this way
<ul id="avia-menu" class="menu av-main-nav">
<li id="menu-item" class="menu-item">
<a href="home">
<span class="avia-bullet"></span>
<span class="avia-menu-text">Home</span>
<span class="avia-menu-fx">
<span class="avia-arrow-wrap">
<span class="avia-arrow"></span>
</span>
</span>
</a>
</li>
<li id="menu-item" class="menu-item">
<a href="about">
<span class="avia-bullet"></span>
<span class="avia-menu-text">About</span>
<span class="avia-menu-fx">
<span class="avia-arrow-wrap">
<span class="avia-arrow"></span>
</span>
</span>
</a>
</li>
<li id="menu-item" class="menu-item">
<a href="contact">
<span class="avia-bullet"></span>
<span class="avia-menu-text">Contact</span>
<span class="avia-menu-fx">
<span class="avia-arrow-wrap">
<span class="avia-arrow"></span>
</span>
</span>
</a>
</li>
</ul>
function updateMenu(url) {
const active = document.querySelector('#menu-item.active');
if (active !== null) {
active.classList.remove('active');
}
const links = Array.from(document.querySelectorAll('#menu-item'));
links.forEach(function (li) {
let anchor = li.querySelector("a");
if (url.indexOf(anchor.href) > -1) {
li.classList.add("active");
}
});
}
updateMenu(window.location.href);
You can simplify your function by consolidating your .add("active") and .remove("active") calls inside your loop. This saves you a query and avoids unsetting and resetting a class on the same element unnecessarily.
You also don't need the Array.from() call.
function updateMenu(url) {
const links = document.querySelectorAll('#menu-item');
links.forEach(li => {
let anchor = li.querySelector("a");
if (url.indexOf(anchor.href) > -1) {
li.classList.add("active");
} else {
li.classList.remove("active");
}
});
}
updateMenu(window.location.href);
I need to enable and disable tab based select results.Below the code I am working.If device B status is On-Line I need to disable Device-V tab.How to implement this using JavaScript/jQuery.
jQuery:
if(result.includes("On-line") ){
$(selected_device_id).html("");
//Need to implement disable function here
$(selected_device_id).append(result+" ✅");
HTML File:
<div class="panel">
<br>
<ul class="nav nav-pills nav-tabs">
<li class="active">
<a
data-toggle="tab"
href="#Device-B"
onclick="document.getElementById('Object').value = '';
document.getElementById('first_i').value = '';
document.getElementById('second_i').value = '';
document.getElementById('third_i').value = '';">
<i>
<b>Device B</b>
</i>
</a>
</li>
<li>
<a
data-toggle="tab"
href="#Device-V"
onclick="document.getElementById('tr181_object').value = '';
document.getElementById('first_i').value = '';
document.getElementById('second_i').value = '';
document.getElementById('third_i').value = '';">
<i>
<b>Video</b>
</i>
</a>
</li>
</div>
$(document).ready(function()
{
var switch_ch = 0 ;
$(".linktoggle").on("click",function(){
i = $(this).index(".linktoggle") ;
if( $(".linktoggle").attr("href") === "#Device-B")
{
if( switch_ch === 0 )
{
$(".linktoggle:eq(0)").show();
$("li:eq(0)").show();
$(".linktoggle:eq(1)").hide();
$("li:eq(1)").hide();
switch_ch = 1 ;
}
else
{
$(".linktoggle:eq(1)").show();
$("li:eq(1)").show();
switch_ch = 0 ;
}
}
if( $(".linktoggle").attr("href") === "#Device-V")
{
$(".linktoggle:eq("+i +")").hide();
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="panel">
<br>
<ul class="nav nav-pills nav-tabs">
<li class="active">
<a
class="linktoggle"
href="#Device-B" >
<i>
<b>Device B</b>
</i>
</a>
</li>
<li>
<a
class="linktoggle"
data-toggle="tab"
href="#Device-V"
>
<i>
<b>Video</b>
</i>
</a>
</li>
</div>
I had a previous code like this:
Basically I added the active status to the li docker logs and open the sub-menu of Docker.
html
<li id="dockerMenu">
<a data-toggle="collapse" href="#docker-pages" aria-expanded="false" aria-controls="testing-main.webapp.pages">
<img src="../resources/img/icons/docker-icon.png" alt="" class="menuIcon">
<span class="menu-title">Docker <i class="fa fa-sort-down"></i></span>
</a>
<div class="collapse" id="docker-pages">
<ul class="nav flex-column sub-menu" data-simplebar>
<security:authorize access="hasAuthority('Administrator')">
<li class="nav-item" id="docker-status">
<a href="/docker-status">
<img src="../resources/img/icons/status.png" alt="">
<span class="menu-title">Container Status</span>
</a>
</li>
...
<ul>
<div>
</li>
var url = window.location.pathname + window.location.search;
if(url === "/docker-logs") {
$('#docker-logs').addClass('active');
$('#dockerMenu a').click();
}
I wanted to do the same on Angular but I don't know how
ngOnInit() {
this.toggleMenus();
}
toggleMenus() {
let url = window.location.pathname;
console.log(url);
switch(url) {
case "/docker-logs":
//how do I activate this?
}
******** EDITED TO SIMPLIFY EXAMPLE AND CLARIFY REQUIREMENT AND PROBLEM **********
I'm stumped with this one, I hope someone can help.
I have a nav bar that I need to run a function on to add .active classes to li elements if they have descendants of a.active.
The menu system is a React component: -
import React, {Component} from "react";
import { Link, NavLink } from 'react-router-dom'
import {activateMenu} from './ActivateMenu'
class SidebarMenu extends React.Component {
componentDidMount() {
activateMenu()
}
componentDidUpdate() {
activateMenu()
}
render() {
const renderNavLink = (to, text, icon, renderArrow = false) => {
return(
<NavLink to={to}>
<i className="bullet">{icon}</i>
<span>{text}</span>
{renderArrow ? <span className="pull-right-container">
<i className="angle-left"><FaAngleLeft /></i>
</span> : null}
</NavLink>
)
}
return (
<ul className="sidebar-menu" data-widget="tree">
<li className="">
{renderNavLink('/','Home',<FaHome />)}
</li>
<li className="treeview">
{renderNavLink("#",'Users',<FaGroup />, true)}
<ul className="treeview-menu">
<li>
{renderNavLink(userSearchSlug,'Search',<FaSearch />)}
</li>
</ul>
</li>
<button onClick={activateMenu}>Press Me</button>
</ul>
)
}
}
export default SidebarMenu
This will give me an HTML structure like this: -
<ul class="sidebar-menu tree" data-widget="tree">
<li class="treeview">
<a href="#">
<i class="fa fa-dashboard"></i> <span>Links</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li>
<i class="fa fa-circle-o"></i> Link1
</li>
<li>
<i class="fa fa-circle-o"></i> Link2
</li>
</ul>
</li>
</ul>
After React has rendered the HTML, I need to trigger a click event on the the .treeview > a node if any a.active nodes are found under .treeview-menu. So: -
<li class="treeview">
<a href="#" *****TRIGGER CLICK EVENT*****>
<i class="fa fa-dashboard"></i> <span>Links</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li>
<i class="fa fa-circle-o *****.ACTIVE CLASS HERE****"></i> Link1
</li>
<li>
<i class="fa fa-circle-o"></i> Link2
</li>
</ul>
</li>
activeMenu() looks like this: -
$('ul.sidebar-menu li.treeview:not(.menu-open)').has('a.active').find('a').trigger( "click" );
This function works when called from onClick() from a button on the page but it is not working in componentDidMount() and componentDidUpdate(). The function will run (tested with console.log() but not affect the HTML as it should. However, if I run it from a Button, it works perfectly. It also works perfectly when HMR runs.
I've no idea why this is happening. Does anyone have any ideas?
This is probably happening because you're selecting the element directly rather than using refs, although it's hard to say because we have no idea what $('ul.sidebar-menu .treeview a').parent().has('a.active').parent().find('.treeview a') is selecting, which is why this kind of code is an antipattern.
React may be in some state where it's not prepared to handle click events at those points. Try using something like the following:
import React, {Component} from "react";
import { Link, NavLink } from 'react-router-dom'
class SidebarMenu extends React.Component {
constructor(props) {
super(props);
this.menuRefs = [];
}
componentDidUpdate() {
if (this.menuRefs.length) {
this.menuRefs[0].click();
}
}
render() {
const renderNavLink = (to, text, icon, renderArrow = false) => {
return(
<NavLink to={to} innerRef={ref => this.menuRefs.push(ref)}>
<i className="bullet">{icon}</i>
<span>{text}</span>
{renderArrow ? <span className="pull-right-container">
<i className="angle-left"><FaAngleLeft /></i>
</span> : null}
</NavLink>
)
}
return (
<ul className="sidebar-menu" data-widget="tree">
<li className="">
{renderNavLink('/','Home',<FaHome />)}
</li>
<li className="treeview">
{renderNavLink("#",'Users',<FaGroup />, true)}
<ul className="treeview-menu">
<li>
{renderNavLink(userSearchSlug,'Search',<FaSearch />)}
</li>
</ul>
</li>
<button onClick={() => this.menuRefs[0] && this.menuRefs[0].click()}>Press Me</button>
</ul>
)
}
}
export default SidebarMenu
Notice
Now there's an array of "menuRefs" and you just use them like normal DOM elements.
We push to the menuRefs in the NavLink innerRef prop (found here)
Note however that you may want to keep a map to ensure that no duplicates get pushed into menuRefs.
To learn more about refs, visit the docs: https://reactjs.org/docs/refs-and-the-dom.html