React onClick event only triggerable once after compiling from jsx to js - javascript

I have a component that builds a list of images with 2 buttons on each array entry.
One of the 2 buttons has an onClick event which updates its parentComponent so that the image is shown in a bigger view.
Everything works perfectly in the precompilex jsx version. But as soon as i try out the "live" compiled version the onClick event only works once.
To make it work on another element I need to reload the page.
I don't get any console errors. No idea where the error might be.
If you want to recreate it you can paste the code and create a div with the id "bilder".
I am using the latest react version :
<script src="some-react-CDN-0.13.3.js"></script>
<script src="some-react-CDN/JSXTransformer-0.13.3.js"></script>
Heres the source :
var Bilder = React.createClass({
getInitialState: function() {
return {
data:[
['1', '/app/public/imgs/image.jpg', 'bild1.jpg'],
['2', '/app/public/imgs/image.jpg', 'bild2.jpg'],
['3', '/app/public/imgs/image.jpg', 'bild3.jpg'],
['4', '/app/public/imgs/image.jpg', 'bild4.jpg'],
['5', '/app/public/imgs/image.jpg', 'bild5.jpg']
],
currentPic:[],
display:'showBild clearfix dn',
displayBg:'darkBg dn'
};
},
showBild: function(e, data){
this.setState({
currentPic: e,
display: 'showBild clearfix db',
displayBg: 'darkBg db'
});
},
hide: function(){
this.setState({
display: 'showBild clearfix dn',
displayBg: 'darkBg dn'
});
},
render: function() {
return (
<div>
<SingleBild data={this.state.data} chosenBild={this.showBild} />
<BildDetail hide={this.hide} data={this.state.currentPic} display={this.state.display} displayBg={this.state.displayBg} />
</div>
);
}
});
var SingleBild = React.createClass({
getInitialState: function() {
return {
bild:[]
};
},
showBild: function(data, e){
e.preventDefault();
this.props.chosenBild(data);
},
render: function() {
var scopeThis = this;
var displayBild = function(bild){
return <li><img src={bild[1]} alt="" /><span>{bild[2]}</span><a onClick={scopeThis.showBild.bind(null, bild)} href="#"><i className="fa fa-eye"></i></a><i className="fa fa-trash-o"></i></li>
};
return (
<ul className="dashboardUl bilder clearfix">
<h2>Gemeldete Bilder:</h2>
{this.props.data.map(displayBild)}
</ul>
);
}
});
var BildDetail = React.createClass({
hide: function(){
this.props.hide();
},
render: function() {
return (
<div>
<div className={this.props.display}>
<img src={this.props.data[1]} alt="" />
<span>{this.props.data[2]}</span>
<ul>
<li><i className="fa fa-trash-o"></i></li>
<li><i className="fa fa-ban"></i></li>
</ul>
</div>
<div onClick={this.hide} className={this.props.displayBg}></div>
</div>
);
}
});
React.render(<Bilder />, document.getElementById('bilder'));

I think you should remove the mapping of data onto list nodes out of the return statement in render and then bind component Class to to the map callback function.
...
render: function() {
var listNodes = this.props.data.map(function(bild) {
return (
<li>
<img src={bild[1]} alt="" />
<span>{bild[2]}</span>
<a onClick={this.showBild} href="#">
<i className="fa fa-eye"></i>
</a>
<a href="#">
<i className="fa fa-trash-o"></i>
</a>
</li>
)
}.bind(this));
return (
<ul className="dashboardUl bilder clearfix">
<h2>Gemeldete Bilder:</h2>
{listNodes}
</ul>
);
}
Now

Related

Vue.js - how to hide an image with the hover event on it and show another?

I have two images whose behavior I want to see next.
By default the image will be shown with the name 'home' and with the event 'mouseover' I want to hide and show the image with the name 'blackhome'.
I have the two images shown on screen and there's nothing happens with the mouse events
I don't know if this is possible.
Here's a codepen link with the issue
https://codepen.io/CharlieJS/pen/gOrayzW
this is my template
<li class="nav-item" #mouseover="homeLink = !homelink" #mouseleave="!homeLink" >
<a class='nav-link home' href="https://www.google.com/">
<img v-if="homeLink" class="logo" src="../../assets/home.png">
<img v-if="!homelink" src="../../assets/blackhome.png">
</a>
</li>
and my script
export default {
data: function () {
return {
homeLink: false
}
},
computed: {
auth () {
return this.$store.getters.isAuthenticated
}
},
methods: {
onLogout() {
this.$store.dispatch('logout')
},
}
}
</script>
Thank you in advance for your time and help
Try v-if and v-else as follows :
<li class="nav-item" #mouseover="homeLink = !homelink" #mouseleave="homeLink=false" >
<a class='nav-link home' href="https://www.google.com/">
<img v-if="homeLink" class="logo" src="../../assets/home.png"/>
<img v-else src="../../assets/blackhome.png"/>
</a>
</li>
let app = new Vue({
el: "#app",
data: function() {
return {
homeLink: false
}
},
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<li class="nav-item" #mouseover="homeLink = !homelink" #mouseleave="homeLink=false">
<a class='nav-link home' href="https://www.google.com/">
<img v-if="homeLink" class="logo" src="https://picsum.photos/300/200?image=244" />
<img v-else src="https://picsum.photos/300/200?image=1024" />
</a>
</li>
</div>

Trying to map array in React, getting not defined

Below is a section of my render and then the component that it references. I am getting "li not defined". I have tried wrapping it in {} and at this point not sure what I am missing. Thanks for the help.
Render section:
var uls = _.chunk(_.take(this.state.results, maxICanShow), perColumn);
return (
<div>
uls.map((lis) => {
<ul className="appt_bd">
<li className="appt_bd_header" style={{ width: colWidth + '%' }}>
<span className="appt_bd_header_main">{this.props.title}</span>
<span className="appt_bd_header_sub">Appts Set</span>
<span className="appt_bd_header_sub">Appts Show</span>
</li>
lis.map((li) => <AppointmentBoardRow key={li.userId} row={li} />)
</ul>
})
</div>
);
Here is the component it references:
var AppointmentBoardRow = React.createClass({
render: function () {
var row = this.props.row;
return (
<li className="appt_bd_row" style={{ width: this.props.colWidth + '%' }} key={row.userId}>
<span className="appt_bd_desc">
<span className="appt_bd_rank">{row.rank}</span>
<span className="appt_bd_avatar_container"><div className={row.className}><span className="initials">{row.initials}</span></div></span>
<span className="appt_bd_user">
<span className="appt_bd_description_main">{row.userName}</span>
<span className="appt_bd_description_sub">{row.role}</span>
</span>
</span>
<span className="appt_bd_data">
<span className="appt_bd_data_main">{row.apptsSetCount}</span>
<span className="appt_bd_data_sub">/{row.apptsSetGoal}</span>
</span>
<span className="appt_bd_data">
<span className="appt_bd_data_main">{row.apptsShowCount}</span>
<span className="appt_bd_data_sub">/{row.apptsShowGoal}</span>
</span>
</li>
);
}
});
It looks like there are a couple of small syntax errors in your first code snippet. Specifically, the call to uls.map is javascript within html syntax, so should be wrapped in {}. The same applies to lis.map.
Additionally, uls.map((lis) => { <ul>...</ul> } is a function that does not return anything. You might instead want to represent it as uls.map((lis) => ( <ul>...</ul> ), or uls.map((lis) => { return (<ul>...</ul>) }. You might want to use the latter and set a debugger to figure out what exactly is happening to the passed in data if the problem still persists.
I took a pass at fixing the syntax errors I mentioned above, hope this helps.
var uls = _.chunk(_.take(this.state.results, maxICanShow), perColumn);
return (
<div>
{
uls.map((lis) => (
<ul className="appt_bd">
<li className="appt_bd_header" style={{ width: colWidth + '%' }}>
<span className="appt_bd_header_main">{this.props.title}</span>
<span className="appt_bd_header_sub">Appts Set</span>
<span className="appt_bd_header_sub">Appts Show</span>
</li>
{ lis.map((li) => <AppointmentBoardRow key={li.userId} row={li} />) }
</ul>
)
}
</div>
);

Looping in React, how to get a prop.username from child component

I have this code, which renders a Friends List block. Next to the name, there is an action dropdown menu, where there are several buttons, i need to seperate each button and on which user it belongs. So far it works, but outputs all the usernames, one by one. Check on the dropdown menu the onClick Alert. There when i press the href, nothing happens, though, when new content loads, it pops up alert foreach user listed.
var UserDropdownActions = React.createClass({
handlesendMessage: function(username){
console.log(username);
},
render: function() {
return(
<div className="tbl-cell tbl-cell-action">
<div className="btn-group">
<button type="button" className="btn btn-rounded btn-primary-outline dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Connect
</button>
<ul className="dropdown-menu">
<li><a className="dropdown-item" href="javascript:;" onClick={alert(this.props.username)}><span className="font-icon font-icon-home"></span>Quant and Verbal</a></li>
<li><a className="dropdown-item" href="javascript:;"><span className="font-icon font-icon-cart"></span>Real Gmat Test</a></li>
<li><a className="dropdown-item" href="javascript:;"><span className="font-icon font-icon-speed"></span>Prep Official App</a></li>
<li><a className="dropdown-item" href="javascript:;"><span className="font-icon font-icon-users"></span>CATprer Test</a></li>
<li><a className="dropdown-item" href="javascript:;"><span className="font-icon font-icon-comments"></span>Third Party Test</a></li>
</ul>
</div>
</div>
);
}
})
var UserDisplayNameFields = React.createClass({
render: function(){
return(
<div className="tbl-cell">
<p className="user-card-row-name status-online">{this.props.username}</p>
<p className="user-card-row-location">{this.props.hobby}</p>
</div>
);
}
});
var UserPreviewCircularImage = React.createClass({
render: function(){
return(
<div className="tbl-cell tbl-cell-photo thumbnail-wrapper d32 circular inline m-t-5">
<a href={"/user/" + this.props.username}>
<img src={this.props.avatar} alt={this.props.username} />
</a>
</div>
);
}
});
var UserSmallView = React.createClass({
render: function() {
return (
<div className="friends-list-item">
<div className={"user-card-row user_" + this.props.username}>
<div className="tbl-row">
<UserPreviewCircularImage avatar={this.props.avatar} username={this.props.username} />
<UserDisplayNameFields username={this.props.username} hobby={this.props.hobby} />
<UserDropdownActions username={this.props.username} />
</div>
</div>
</div>
);
}
});
var FriendList = React.createClass({
render: function() {
return (
<div className="friends-list">
{
this.props.users.map( (user, i) => {
return(
<UserSmallView
key={i}
username={user.username}
hobby={user.hobby}
avatar={user.avatar} />
)
})
}
</div>
);
}
});
My mistake was that i was trying to send to the function the username, though, it was already there.
i added a function where it alerts the prop.username
handlesendMessage: function(){
alert(this.props.username);
},
instead of,
handlesendMessage: function(username){
alert(username);
}

How should I be using ko.applyBindings ? I am getting an error when using this

My script is the following:
#using (Html.BeginFooterScripts())
{
<script type="text/javascript" src="//ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"></script>
<script type="text/javascript" src="/Content/Northwestern/js/_libs/knockout.mapping/knockout.mapping.2.4.1.js"></script>
<script type="text/javascript" src="~/Content/Northwestern/js/views/TabPanel/location-card.js"></script>
<script type="text/javascript">
$(function() {
initialize();
});
</script>
<script>
$(function() {
// we must be on a detail page, we don't have a current location, so get it!
if (viewModel.currentLocation.latitude == 0 || viewModel.currentLocation.longitude == 0) {
geoLocate(function(location) {
viewModel.currentLocation.latitude = location.coords.latitude;
viewModel.currentLocation.longitude = location.coords.longitude;
displayLocation('#Model.LocationId');
}, geoLocateError);
} else {
displayLocation('#Model.LocationId');
}
});
</script>
}
my external script is :
/**********************************************
* Global variables
**********************************************/
var applied = false;
var geoLocateError = function onError(error) {
alert(error.message);
};
function ViewModel() {
var self = this;
self.currentLocation = {
latitude: 0,
longitude: 0
};
self.LocationId = ko.observable();
}
var viewModel = new ViewModel();
$(function () {
});
function initialize() {
ko.applyBindings(viewModel);
geoLocate(function(location) {
initLocation(location);
}, geoLocateError);
}
/**********************************************
* Location Functions
**********************************************/
function initLocation(location) {
viewModel.currentLocation = {
latitude: location.coords.latitude,
longitude: location.coords.longitude
};
}
function displayLocation(id) {
var apiUrl = '/api/northwestern/locations/getlocationbyid/' + id;
var data = {
'latitude': viewModel.currentLocation.latitude,
'longitude': viewModel.currentLocation.longitude
};
self.LocationId = id;
$.getJSON(apiUrl, data, function (response) {
var fragment = document.createDocumentFragment(),
container = document.createElement('div'),
viewModel = response;
fragment.appendChild(container);
// merge together all the display types into a commma-separated list
response.TypeListDisplay = $.map(response.Types, function (obj, t) {
return obj.ItemName;
}).join(', ');
ko.renderTemplate(
"location-detail-template",
viewModel, {
afterRender: function () {
$('#detail-container').html(container.innerHTML);
}
},
container
);
});
}
and here is the markup :
<div class="row">
<div class="col md-4">
<div class="section-content">
<div id="detail-container">
</div>
</div>
<script type="text/html" id="location-detail-template">
<div class="card card-locations-alt">
<div class="card-content">
<figure class="map">
<a target="_blank" href="https://www.google.com/maps/dir/Current+Location/#Model.Location.Latitude, #Model.Location.Longitude">
<img src="https://maps.googleapis.com/maps/api/staticmap?center=#Model.Location.Latitude,#Model.Location.Longitude&zoom=13&size=65x65&maptype=roadmap&markers=color:0x776EA7%7Clabel:%7C #Model.Location.Latitude,#Model.Location.Longitude">
</a>
</figure>
<div class="location-content" itemscope="" itemtype="http://schema.org/LocalBusiness">
<div class="location-name">
<h2 class="location-title" itemprop="name" data-bind="text: ItemName"></h2>
</div>
<div class="distance">
<i class="material-icons">place</i> <span data-bind="text: Distance.toFixed(1)"> Mi</span>
</div>
<div class="location-phone">
<a data-bind="attr: { 'href': clickToCallify(Phone), 'data-track-event': 'Find a Location - Detail', 'data-track-action': 'call icon' }" class="tel" itemprop="telephone"></a>
</div>
</div>
<div class="location-actions flex-container align-center no-print">
<a class="locations-icon flex-item tel" href="tel:8475358000">
<div class="call-icon uppercase">
<i class="material-icons">phone</i><br>
call
</div>
</a>
<a data-bind="attr: {'href' : 'https://www.google.com/maps/dir/Current+Location/' + Latitude + ',' + Longitude, 'data-track' : 'Find a Location', 'data-track-action' : 'directions', 'data-track-label' : ItemName }" target="_blank" class="locations-icon flex-item uppercase">
<i class="material-icons">directions</i><br>
directions
</a>
<a href="" class="location-detail locations-icon flex-item uppercase">
<i class="material-icons">info</i><br>
details
</a>
</div>
</div>
</div>
</script>
</div>
<div class="col md-7">
#(new HtmlString(Model.Body))
</div>
</div>
<br />
}
now, when I applyBindingsviewModel) under the initialize function, it works the first time, then it throws an error "cannot apply bindings muliple times for the same element.
I have tried to do a ko.cleanNode, but that did not work.
when i take the applyBindings off, I don't get the error, but the program skips over all but the last page component.
The problem is cause binding applies two times to the same elements. So the can be some other knockout binding in your code or initialize function executes second time.
If you have few models which you would like to bind to your page you can use second parameter of applyBindings, if you do not pass it model binds to body.
Optionally, you can pass a second parameter to define which part of the document you want to search for data-bind attributes.
http://knockoutjs.com/documentation/observables.html

jQuery click event happening on parent DIV when using stopPropagation

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
jQuery(document).ready(function() {
//Add Header Listeners
//Signup Listener
jQuery(".top-nav-login-links .exchange-signup").click(headerObject.toggleLightBoxSignup.bind(headerObject));
//Login Listener
jQuery(".top-nav-login-links .exchange-login").click(headerObject.toggleLightBoxLogin.bind(headerObject));
//Lightbox Close Listeners
jQuery("i.close-lightbox, div.light-box-parent").click(function(e) {
e.stopPropagation();
if(jQuery(this).attr("data-rel") == "signUpVisible") {
headerObject.toggleLightBoxSignup();
} else if(jQuery(this).attr("data-rel") == "loginVisible") {
headerObject.toggleLightBoxLogin();
}
});
});
var headerObject = {
isLoginLightBoxVisible : false,
isSignupLightBoxVisible : false,
isCookiesBannerVisible : true,
showServicesDropdown : false,
isMobileMenuVisible : false,
layoutElement : document.querySelector('#layout'),
toggleLightBoxLogin : function() {
jQuery("#loginVisible").toggle();
},
toggleLightBoxSignup : function() {
jQuery("#signUpVisible").toggle();
},
toggleMobileMenu : function() {
if (!this.isMobileMenuVisible) {
this.layoutElement.classList.add("active");
} else {
this.layoutElement.classList.remove("active");
}
this.isMobileMenuVisible = !this.isMobileMenuVisible;
},
closeCookiesBanner : function() {
this.isCookiesBannerVisible = false;
//localStorage.setItem('this.isCookiesBannerVisible', 'false');
},
onMenuItemClick : function() {
if (('ontouchstart' in window) || window["DocumentTouch"] && document instanceof DocumentTouch) {
event.preventDefault();
event.stopPropagation();
}
}
};
</script>
<div class="top-nav-login-links">
<ul>
<li class="pure-hidden-phone"><a class="exchange-signup" href="#">Sign up</a></li>
<li class="pure-hidden-phone"><a class="login exchange-login" href="#">Log in</a></li>
<li class="pure-hidden-tablet pure-hidden-desktop" data-ng-click="viewModel.toggleLightBoxLogin()"><i class="fa fa-user login-cta login"></i></li>
</ul>
</div>
</div>
</section>
<div id="loginVisible" class="light-box-parent login-lightbox" data-rel="loginVisible">
<div class="light-box-options">
<div class="light-box-container" >
<figure class="login-figure">
<a id="link-expert-login" href="http://experts.blurgroup.com/">
<img id="img-login-expert" src="<?php echo get_template_directory_uri(); ?>/images/shared/login_expert_logo.png" alt="Expert">
<figcaption class="login-figcaption">Expert</figcaption>
</a>
</figure>
<figure class="login-figure customer-login">
<a id="link-customer-login" href="/customer/">
<img id="img-login-customer" src="<?php echo get_template_directory_uri(); ?>/images/shared/login_customer_logo.png" alt="Customer">
<figcaption class="login-figcaption">Customer</figcaption>
</a>
</figure>
</div>
<div class="light-box-title">Login</div>
<i class="fa fa-times-circle"></i>
</div>
</div>
<div id="signUpVisible" class="light-box-parent expert-sign-up" data-rel="signUpVisible">
<div class="light-box-options">
<div class="light-box-container">
test
</div>
<div class="light-box-title">New to blur Group? Join the crowd</div>
<i class="fa fa-times-circle close-lightbox" data-rel="signUpVisible"></i>
</div>
</div>
I am currently implementing some lightboxes which open on certain anchor ticks being click. I then have the functionality whereas when the lightbox itself or an icon within it (with the class 'close' is clicked) it should close the appropriate lightbox according to the value stored in a 'data-rel' HTML5 data attribute.
The problem I am having is that the click event is propagating to any child element within the lightbox, even when I have targeted the specific elements themselves and used event.stopPropagation().
I can't figure out why this is happening. Can someone see a problem with my code?
Thanks
Try using stopImmediatePropagation function in place of stopPropagation

Categories

Resources