I am trying to get something like x-editable inline edit in reactjs. I am able to get the HTML form/control inside the bootstrap tooltip, however, not able to set or change value on the input control on the popover. Below is the code.
class Inline extends React.Component {
constructor(props, context) {
super(props, context);
this.state= {
displayText: props.displayText,
valueText : props.valueText
}
}
componentDidMount() {
$("[data-toggle=popover]").popover({
html: true,
content: function() {
return $('#popover-content').html();
}
});
$(document).on("click", ".popover .close" , function(){
$(this).parents(".popover").popover('hide');
});
}
onChange(e) {
console.log('on change : ' + e.target.value)
this.setState({ displayText: e.target.value });
}
handleClick (e) {
e.preventDefault();
console.log('The link was clicked.');
}
render(){
return (
<div className="container">
<ul className="list-unstyled inline-edit">
<li><a data-placement="bottom" data-toggle="popover" data-title="Inline Edit <a href='#' class='close' data-dismiss='alert'>×</a>" data-container="body" type="button" data-html="true" href="#" >{this.state.displayText}</a></li>
<div id="popover-content" className="hide">
<div className="form-group">
<span>{this.state.displayText}</span>
<input type="text" placeholder="Name" className="form-control"
value={this.state.displayText}
onChange={this.onChange}
></input>
<div className="form-group edit-control">
<a href="#" role="button" onClick={this.handleClick}><i className="fa fa-check-circle fa-2x green"/></a>
<a href="#" role="button" ><i className="fa fa-times-circle fa-2x red leftpad"/></a>
</div>
</div>
</div>
</ul>
</div>
);
}
};
Inline.propTypes = {
displayText: PropTypes.string.isRequired,
valueText: PropTypes.string.isRequired
};
export default Inline;
Screen shot
The issue is in the way your popover is created:
componentDidMount() {
$("[data-toggle=popover]").popover({
html: true,
content: function () {
return $('#popover-content').html();
}
});
}
You are using jquery html() function to duplicate a Html DOM element in the bootstrap popover. When duplicating an html element this way, the JavaScript React logic is not attached to the duplicated html code.
You can't only use the bootstrap tool tip to created the popover. You have to:
Either manually instantiate a react component in the popover (using the ReactDom render function).
Or (the better solution I think) use the dedicated react bootstrap lib that provide the popover bootstrapreact component
Related
I am trying to display FontAwesomeicon
<font-awesome-icon icon="fa-solid fa-shop" />
with JavaScript array to be dynamic but it's not working it displays as text
<div class="aboutme-card" v-for="(item,index) in servicesArr" :key="index">
<div class="service-card-icon">{{item.icon}}</div> <!--but its display as text not as icon svg-->
<div class="service-card-title">{{item.title}}</div>
<p class="service-card-desc">{{item.description}}</p>
</div>
<script>
export default {
data() {
return {
servicesArr: [
{
icon: `<font-awesome-icon icon="fa-solid fa-shop" />`,
title: "E-commerce",
}
]
}
}
}
</script>
Isn't something like this conceivable in your case?
<template>
<div class="aboutme-card" v-for="item in servicesArr" :key="item.icon">
<div class="service-card-icon">
<font-awesome-icon :icon="item.icon" />
</div>
</div>
</template>
<script>
export default {
data() {
return {
servicesArr: [
{
icon: "fa-solid fa-shop",
title: "E-commerce",
}
]
}
}
}
</script>
Even if v-html exists, it's usually not the way to go.
Especially in such a simple use-case where dynamic props are totally fine.
Overall, I still recommend that solution for overall ease of use + flexibility.
I have been racking my brain how I could include a toggle menu on my website, after some searching I found the below and have implemented it, which is great!
http://jsfiddle.net/hhcsz5cr/
<div>
<h1><button class="button" data-circle="travel">
<i class="fa fa-plus-square"></i>
</button> Travel</h1>
</div>
<div class="travel options">
<ul>
<li>Travel</li>
<li>Vehicles</li>
</ul>
</div>
var localStorageKey = "app_state";
// to preserve state, you first need to keep track of it
var default_state = {
biographies: false,
pictures: false,
poetry: false
}
var saved_state = localStorage.getItem(localStorageKey);
// ternary operator which means if `saved_state` is true we parse it and use that value for `state`; otherwise use `default_state`
var state = saved_state ? JSON.parse(saved_state) : default_state;
$(function() {
init();
$('.button').on('click', function() {
var circle = $(this).attr('data-circle');
toggleCircle(circle, !state[circle]);
$(this).find('i').toggleClass('fa-minus fa-plus');
});
});
function init() {
for(var key in state) {
var is_displayed = state[key];
if ( is_displayed ) {
$(this).find('i').toggleClass('fa-minus fa-plus');
} else {
$(this).find('i').toggleClass('fa-plus fa-plus');
}
console.log(is_displayed);
toggleCircle(key, is_displayed);
}
}
function toggleCircle(circle, is_displayed) {
if (is_displayed) {
$('.'+circle).show()
state[circle] = true;
} else {
$('.'+circle).hide()
state[circle] = false;
}
localStorage.setItem(localStorageKey, JSON.stringify(state));
}
But.. if you minimize a menu then refresh the icon shows a - even though its already minimize.
Is there any way I can change this?
I realise the code above is not my own and I can't find the person to credit! My jquery is terrible.
Any help would be appreicated.
Thanks
jsFiddle DEMO (since SO snippets do not allow localStorage from Iframe)
Use IDs, not classes. IDs are unique, not classes.
Store the entire ID as the object property i.e: "#pictures": false,
Store the entire selector inside data-* i.e: data-toggle="#biographies"
Use "is-*" classes as state CSS helpers: "is-hidden", "is-expanded"
You don't have to use .fa classes, just use CSS and font-family
Make use of Object.assign() to override your default values with the ones in Local Storage (if any).
Loop your object key value pairs using Object.entries() when initing your menu states.
// Override defaults with localStorage
const state = Object.assign({
"#biographies": false, // Feel free to change this default boolean
"#pictures": false,
"#poetry": false
}, JSON.parse(localStorage.state || "{}"));
const toggle = (k, v) => {
$(k).toggleClass('is-hidden', !v);
$(`[data-toggle="${k}"]`).toggleClass('is-expanded', v);
};
// On init
Object.entries(state).forEach(([k, v]) => toggle(k, v));
// On click
$("[data-toggle]").on("click", function() {
const id = this.dataset.toggle; // Get ID i.e: "#pictures"
state[id] = !state[id]; // Flip boolean
toggle(id, state[id]); // Trigger UI changes
localStorage.state = JSON.stringify(state); // Store into LS
});
.is-hidden {
display: none;
}
[data-toggle] i:before{
font-family: "FontAwesome";
font-style: normal;
content: "\f067"; /* Plus */
}
[data-toggle].is-expanded i:before{
content: "\f068"; /* Minus */
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css">
<div id="biographies" class="is-hidden">Biography</div>
<div id="pictures" class="is-hidden">Pictures</div>
<div id="poetry" class="is-hidden">Poetry</div>
<button type="button" class="button" data-toggle="#biographies">
<i></i> biographies
</button>
<button type="button" class="button" data-toggle="#pictures">
<i></i> pictures
</button>
<button type="button" class="button" data-toggle="#poetry">
<i></i> poetry
</button>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
Please try this..
$('.button').click(function(){
var whichbtn = $(this).attr('data-circle');
if($("."+whichbtn).hasClass("hidden")){
$(this).children("i").removeClass("fa-plus").addClass("fa-minus");
}else{
$(this).children("i").addClass("fa-plus").removeClass("fa-minus");
}
$("."+whichbtn).toggleClass("hidden");
});
.hidden{display:none;}
.button{
background:#00cc00;
padding:10px 20px;
margin-right:10px;
border:none;
color:white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet"/>
<div class="m-3">
<div class="biographies hidden mb-2 font-weight-bold">Biography</div>
<div class="pictures hidden mb-2 font-weight-bold">Pictures</div>
<div class="poetry hidden mb-2 font-weight-bold">Poetry</div>
<button class="button" data-circle="biographies">
<i class="fa fa-plus"></i> biographies
</button>
<button class="button" data-circle="pictures">
<i class="fa fa-plus"></i> pictures
</button>
<button class="button" data-circle="poetry">
<i class="fa fa-plus"></i> poetry
</button>
</div>
I add js for click event of button and get the attribute of data-circle of it's own for find which button clicked. And fa fa-plus icon changed to fa fa-minus also. Thats only.
toggleClass is used for toggle class when user click the button. First click add class hidden then second click remove class hidden.For more clarifications comment me.
I have created 2 buttons, each button will replace content based on partial views, I could load the partial view on the page when I click the button, but this works only once, for instance I clicked button-1 and loaded data, now if I click on button 2 its not working, I needed to go back to main page to click again on button-2
<h3>
<a class="btn btn-warning" id="button1"> Partial View 1</a>
</h3>
<br/>
<h4>
<a class="btn btn-warning" id="buttton2"> Partial view 2</a>
</h4>
<br/> <br/>
<div id="testsim">
</div>
<script type="text/javascript">
$(function () {
$('#button1').click(function () {
$.get('#Url.Action("partialview1", "Home")', function (data1) {
if (data1) {
$('#testsim').replaceWith(data);
}
});
});
$('#button2').click(function () {
$.get('#Url.Action("partialview2", "Home")', function (data2) {
if (data2) {
$('#testsim').replaceWith(data2);
}
});
});
});
</script>
I'm trying to achieve button clicks to toggle between two buttons, everytime button click should replace the content in div tag. Any help would be appreciated.
I think the problem is because of replaceWith() which replaces the element itself i.e. outerHTML-
$(function() {
let $html, current;
$('#button1').click(function() {
/* $.get('#Url.Action("partialview1", "Home")', function(data1) {
if (data1) {
$('#testsim').replaceWith(data);
}
});*/
current = `button 1 was <em>clicked</em>`;
$html = `<div><strong>${current}</strong></div>`;
$('#testsim').replaceWith($html);
});
$('#button2').click(function() {
/*$.get('#Url.Action("partialview2", "Home")', function(data2) {
if (data2) {
$('#testsim').replaceWith(data2);
}
});*/
current = `button 2 was <strong>clicked</strong>`;
$html = `<div><em>${current}</em></div>`;
$('#testsim').replaceWith($html);
});
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h3>
<a class="btn btn-warning" id="button1"> Partial View 1</a>
</h3>
<br/>
<h4>
<a class="btn btn-warning" id="button2"> Partial view 2</a>
</h4>
<br/> <br/>
<div id="testsim" style="background: aquamarine; height: 200px">
</div>
As you can see that the styling of the element disappears after replacing. If you want to perform this operation then you should use html() which replaces only innerHTML-
$(function() {
let $html, current;
$('#button1').click(function() {
/* $.get('#Url.Action("partialview1", "Home")', function(data1) {
if (data1) {
$('#testsim').replaceWith(data);
}
});*/
current = `button 1 was <em>clicked</em>`;
$html = `<div><strong>${current}</strong></div>`;
$('#testsim').html($html);
});
$('#button2').click(function() {
/*$.get('#Url.Action("partialview2", "Home")', function(data2) {
if (data2) {
$('#testsim').replaceWith(data2);
}
});*/
current = `button 2 was <strong>clicked</strong>`;
$html = `<div><em>${current}</em></div>`;
$('#testsim').html($html);
});
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h3>
<a class="btn btn-warning" id="button1"> Partial View 1</a>
</h3>
<br/>
<h4>
<a class="btn btn-warning" id="button2"> Partial view 2</a>
</h4>
<br/> <br/>
<div id="testsim" style="background: aquamarine; height: 200px">
</div>
Hope this helps you.
I am having a tile. Clicking anywhere on it should redirect to a new page.I have kept my complete code inside Link tag so that whenever i will click on any part of that div, it will navigate to the new page. But inside that Link tag, there is a subdiv, clicking on which i don't want to perform redirection.
The problem i am facing is that if i will close the link tag before that particular div on which i don't want to perform redirection then, remaining area of the parent div is also becoming non-clickable except the written p tags. How i can make only that particular div non-redirectable.
<Link to={{ pathname: '/demo_summary/'>
<div className="ctd-tile" style={{ margin: "10px", height"260px" }}>
<p>VERSION: {i.version}</p><br />
<p>Complexity: {i.complexity}</p><br />
<div className="col-md-4">}}>
<img src={require("../images/icon1.png")} title="DEMO PLAN" /></Link>
</div>
<div className="col-md-4">
<input type="image" title="View HTML" src={require("../images/viewAsHtml.png")} style={{width: "40%", cursor: "pointer"}} onClick={(e) => { e, that.openReport(e, i.demoName) }}/>
</div>
<div className="col-md-4">
<Download file={i.name} content={text}>
<img src={require("../images/download.png")} title="DOWNLOAD" style={{ width: "25%", cursor: "pointer" }} />
</Download>
</div>
</div>
</Link>
I want to make second div having title as "View HTML" to be non-redirectable.
Pass the history to your component as prop then use push to redirect or stop the event with
e.stopPropagation();
Example:
const navigation = ({ history }) => {
return (
<div>
<a
onClick={() => {
history.push("/cool");
}}
>
rediction
<span
onClick={e => {
e.stopPropagation();
}}
>
none redirection
</span>
</a>
</div>
);
};
You need to use event.stopPropagation on the onClick of the div you want to stop redirecting.
When you have nested tags, if you click on one tag, you will trigger the onClick of the tag and the parent onClick too.
function App() {
return (
<div onClick={() => console.log('parent onClick')} >
<button onClick={() => console.log('button click')}>Click me</button>
</div>
)
}
const rootElement = document.getElementById("app");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>
But if you use event.stopPropagation on the children div. The parent tag wont have it onClick event triggered.
function App() {
return (
<div onClick={() => console.log('parent onClick')} >
<button onClick={e => {
e.stopPropagation()
console.log('button onClick')
}}>Click me</button>
</div>
)
}
const rootElement = document.getElementById("app");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>
So now you know that, just add e.stopPropagation() to the onClick of the div you don't want to trigger the Link's onClick.
Edit:
Your code have something very weird
onClick={(e) => { e, that.openReport(e, i.demoName) }} // ????
But what you should do is
onClick={(e) => {
e.stopPropagation();
that.openReport(e, i.demoName);
}}
Here is the full code
<div className="col-md-4"
onClick={(e) => {
// added stopPropagation in the correct place
e.stopPropagation();
that.openReport(e, i.demoName);
}}
>
<input
type="image"
title="View HTML"
src={require("../images/viewAsHtml.png")}
style={{width: "40%", cursor: "pointer"}}
onClick={(e) => {
// added stopPropagation in the correct place
e.stopPropagation();
that.openReport(e, i.demoName);
}}
/>
</div>
Let's assume that I have Angular 5 project with routings. For instance /home, /landing-page, etc. Moreover, let's assume that in my landing page with url - localhost:4200. I want to create login panel. I have two fields - username and password, one button sign in and two other buttons forgot password? and Don't have an account?. My problem is that when user will click Forgot password? or Don't have an account? he will not be routed to another page with url like localhost:4200/sign-up but he will stay at the same page with url localhost:4200 and fields username, password, sign in, forgot password? and Don't have an account? will disappear and in their place will be displayed fields associated with registration. I am not sure whether you know what I mean. The good example what I wanna to achieve is https://www.instagram.com. No matter whether you click Sign up or Log in you are still on the same url and only one component changes. Do you know how can I achieve this? I am not sure whether I should use routes or maybe another way is more optimal to do this? Thanks in advance.
My code looks in this way. I added only the most important code from selected files.
index.html:
</head>
<body>
<app-root></app-root>
</body>
</html>
app.component.html:
<app-navbar></app-navbar>
<router-outlet></router-outlet>
<app-footer *ngIf="removeFooter()"></app-footer>
At the moment my home.component looks in this way:
home.component.html:
<div *ngIf="isSignIn()">
<app-sign-in></app-sign-in>
</div>
<div *ngIf="isSignUp()">
<app-sign-up></app-sign-up>
</div>
<div *ngIf="isForgotPassword()">
<app-forgot-password></app-forgot-password>
</div>
home.component.ts:
constructor() {
this.signin = true;
this.signup = false;
this.forgot = false;
}
isSignUp() {
if (this.signup === true) {
return true;
}
else {
return false;
}
}
isSignIn() {
if (this.signin === true) {
return true;
}
else {
return false;
}
}
isForgotPassword() {
if (this.forgot === true) {
return true;
}
else {
return false;
}
}
sign-in.component.html:
<div class="content-center">
<div class="container">
<div class="title-brand">
<div align="center">
<input style="background-color: black; border-color: white; color:white; width: 270px" type="text" value="" class="form-control" placeholder="USERNAME">
<br>
<input style="background-color: black; border-color: white; color:white; width: 270px" type="text" value="" class="form-control" placeholder="PASSWORD">
<div class="row">
<div class="col-md-8">
<br>
<button style="background-color: black; border-color: white; color:white; width: 270px" type="button" class="btn btn-danger">Log in</button>
</div>
</div>
<br>
<h6 style = "color: white" [routerLink]="['/main']" skipLocationChange class=pointer>Forgot Password?</h6>
<h6 style="color: white" [routerLink]="['/sign-up']" class=pointer>Don't have an account?</h6>
</div>
</div>
</div>
</div>
UPDATE
I added source code of sign-in.component.html to the question. Can you show me how I can switch the component sign-in.component.html after clicking Forgot Password? or Do not have an account? to the component forgot.component.html or sign-up.component.html
Use skipLocationChange from the route NavigationExtras. E.g.
<h6 style = "color: white" [routerLink]="['/main']" skipLocationChange>Forgot Password?</h6>
<h6 style="color: white" [routerLink]="['/sign-up']" skipLocationChange>Don't have an account?</h6>
Here is an example of using a boolean and buttons to allow you to switch between different components on a single page:
stackblitz example
This example could be improved but I hope it shows you how to easily swap the visible component.
You can view the code at this link
EDIT
You need to remove the responsibility of what component to show to a container component (i.e. a parent component). In the updated stackblitz example I've made the HomeComponent responsible for showing the correct component. This means the SignUp/SignIn/ForgotPassword components have no responsibility for switching between each other - that is the job for the HomeComponent (or whichever component you want to use for that job).
Hope that helps
home.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-home',
template:
`<div *ngIf="signin">
<app-sign-in></app-sign-in>
<button (click)="showSignUp()">Sign up</button>
<button (click)="showForgot()">Forgot password</button>
</div>
<div *ngIf="signup">
<app-sign-up></app-sign-up>
<button (click)="showSignIn()">Sign in</button>
<button (click)="showForgot()">Forgot password</button>
</div>
<div *ngIf="forgot">
<app-forgot-password></app-forgot-password>
<button (click)="showSignUp()">Sign up</button>
<button (click)="showSignIn()">Sign in</button>
</div>`,
styles: [`h1 { font-family: Lato; }`]
})
export class HomeComponent {
public signup: boolean = true;
public signin: boolean = false;
public forgot: boolean = false;
constructor() {}
public showSignIn() {
this.signin = true;
this.signup = this.forgot = false;
}
public showSignUp() {
this.signup = true;
this.signin = this.forgot = false;
}
public showForgot() {
this.forgot = true;
this.signin = this.signup = false;
}
}