I'm new to ReactJS and I fell I'm missing some fundamental information.
I am working on simple TODO list, where you click on <li> and it gets transfered to Finished section.
http://jsbin.com/gadavifayo/1/edit?html,js,output
I have 2 arrays that contain list of tasks, when you click on one task <li> it is removed from array and transferred to other array. After that clicked <ul> is updated but not the one where task went.
When using it you may notice that <ul> is updated only when clicked.
How can I update both <ul> when clicking on only one?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Testing</title>
<link rel="stylesheet" href="bootstrap.css">
</head>
<body>
<div id="react-app"></div>
<script src="https://fb.me/react-0.14.3.js"></script>
<script src="https://fb.me/react-dom-0.14.3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
<script type="text/babel">
/*
* Components
*/
var pendingItems = [
'Clean the room',
'Get milf',
'Sellout and stuff'
];
var finishedItems = [
'Clean the room',
];
var TodoList = React.createClass({
getInitialState: function() {
return { items: this.props.list };
},
handleClick: function(i) {
console.log('You clicked: ' + i + ':' + this.props.listString);
if (this.props.listString == "pendingItems") {
var removed = this.state.items.splice(i, 1);
finishedItems.push(removed);
};
if (this.props.listString == "finishedItems") {
var removed = this.state.items.splice(i, 1);
pendingItems.push(removed);
};
this.forceUpdate()
},
render: function() {
return (
<ul>
{this.state.items.map(function(item, i) {
return (
<li onClick={this.handleClick.bind(this, i)} key={i}>{this.state.items[i]}</li>
);
}, this)}
</ul>
);
},
});
var Layout = React.createClass({
render: function (){
return (
<div className='col-xs-12'>
<div className='col-xs-6'>
<TodoList list={pendingItems} listString="pendingItems"/>
</div>
<div className='col-xs-6'>
<TodoList list={finishedItems} listString="finishedItems"/>
</div>
<div className='col-xs-6'></div>
</div>
)
}
});
ReactDOM.render(<Layout />, document.getElementById('react-app'));
</script>
</body>
</html>
You need to use the states. In getInitialState you put your two list, onclick do whatever transformationyou want (you then have for example updated_list1 and updated_list2 and then you set the list like that:
this.setState({ list1: updated_list1, list2: updated_list2 }); in your case this.setState({ pendingItems: pendingItems ... after the .push
the setState function will automatically rerender, no need to call forceupdate.
The second thing important here is that you have to make the two list communication kinda, so my advise would be to put your both ul in the same component (so you can manage the lists in the same component state as mentionned above).
However this is not the only way to go and you may choose the put the states of your two list in the parent component (Layout). In this case you should use this way to go. https://facebook.github.io/react/tips/expose-component-functions.html
In any case you need (if you want to keep it simple and without external model management like backbone or flux pattern) to put lists states in the same component state. (reminder: method 1 => ul in the same componenet so the states too, method 2 => keep state in the parent component)
I'm trying to implement this example for Twitter-Bootstrap tabs http://www.dba-resources.com/scripting-programming/ajax-tabs-in-bootstrap-2-1/ loading content via AJAX, but I need to load the content from a div container within the same document, rather than loading multiple documents. The code I'm using is as follows:
jQuery
$(function() {
$("#MainTabs").tab();
$("#MainTabs").bind("show", function(e) {
var contentID = $(e.target).attr("data-target");
var contentURL = $(e.target).attr("href");
if (typeof(contentURL) != 'undefined')
$(contentID).load(contentURL, function(){ $("#MainTabs").tab(); });
else
$(contentID).tab('show');
});
$('#MainTabs div[data-target="#tabone"]').tab("show");
});
HTML
<ul id="MainTabs" class="nav nav-tabs">
<li><div data-target="#tabone" data-toggle="tab">tab One</div></li>
<li><div data-target="#tabtwo" data-toggle="tab" href="/test.html">Tab Two</div></li>
<li><div data-target="#tabthree" data-toggle="tab" href="/test2.html">Tab Three</div></li>
</ul>
<div class="tab-content">
<div class="tab-pane" id="tabone">Content Tab One</div>
<div class="tab-pane" id="tabtwo">Loading...</div>
<div class="tab-pane" id="tabthree">Loading...</div>
</div>
Thank you in advance for any help.
That should be the default behavior if you just pass in the id of the container to the href.
<li><div data-target="#tabone" data-toggle="tab" href="#loadedcontent">tab One</div></li>
....
<div id="loadedcontent">My content</div>
Since you have a special case where you want to load a specific container of the page through an AJAX call. You can do something like this.
HTML
<li><div id="specialTab" data-target="#tabone" data-toggle="tab" href="/ajax.html">tab one</div></li>
JS
$('#specialTab').click(function(e) {
e.preventDefault();
var containerId = '#content'; /** Specify which element container */
var self = $(this);
var url = self.attr('href');
$(self.data('target'))
.load(url +' '+ containerId, function(){
self.tab('show');
});
});
I'd like to do something like this fiddle only this works on buttons instead of links:
http://jsfiddle.net/qNhZj/
I need it to work on links and also i have an intro div which gets hidden after clicking on one of the links.
Can anyone help me out please.
You just have to declare link instead of input.
In the class list, add the id of the div you want to show.
Click a button to make it visible:
<div id="intro-tekst">Intro text here !</div>
<div class="boxes" id="coke">Coke is awesome!</div>
<div class="boxes" id="bubble-tea">Bubble tea is da bomb!</div>
<div class="boxes" id="milk">Milk is healthy!</div>
<br />
<p>
I change my mind:
<ul>
<li>Coke</li>
<li>Bubble Tea</li>
<li>Milk</li>
</ul>
</p>
And bind it like this :
$(document).ready(function() {
var url = window.location.href;
var option = url.match(/option=(.*)/);
if (option !== null) {
$(".link ." . option[1]).trigger('click');
}
$(".link").bind('click', function () {
$('#intro-tekst').hide();
$('.boxes').hide();
$('.link').removeClass('selected');
$(this).removeClass('link');
$('#' + $(this).prop('class')).show();
$(this).addClass('link selected');
});
});
JsFiddle code here : http://jsfiddle.net/Pq5Cv/8/
I'm sure this is a common question but I have an input field and a button. Whenever the button is pressed an ajax call is performed returning a string. I understand that if you attach it to a div in the original file, that div will erase any strings or numbers in it and replace with the returned string. What would be the most efficient way to allow for every single callback to be displayed on the screen real time? I attempted it but it appears that dynamically changing the javascript variable that assigns which div tag the ajax callback inserts into does not work. Does anyone know either what is wrong with this code or a more efficient way to write this code, i.e. with php, etc.
<div id="part1">
<input type="text" id="text"/>
<input type="button" value="button" id="button"/>
</div>
<div id="hidden" class="2"></div>
<div id="part2"></div>
<div id="part3"></div>
<div id="part4"></div>
<div id="part5"></div>
<script type="text/javascript" >
$('#button').click(function () {
var text = $('#text').val();
$.post('ajaxskeleton.php', {
red: text
}, function(){
var number = $('#hidden').attr("class");
$('#part' + number).html(text);
var number = number+1;
var class_name = $('#hidden').attr('class')
$('#hidden').removeClass(class_name);
$('#hidden').addClass(number);
$('#text').val('');
});
});
</script>
Instead of erasing its contents with .html(), you could append the new results to an existing div . For example, suppose you want to append the results to a div with id results:
$('#button').click(function () {
var text = $('#text').val();
$.post('ajaxskeleton.php', { red: text }, function() {
$("<li>" + text + "</li>").appendTo($("#results"));
});
});
Here's a DEMO.
I think something like the following would work.
<div id="container">
<input type="text" id="text"/>
<input type="button" value="button" id="button"/>
</div>
<ol id="responses"></ol>
$("#button").click(function() {
$.post('ajaxskeleton.php', {red:text}, function(data) {
$("#responses").append("<li>" + data + "</li>");
});
});
This just builds up an ordered list with the responses that come back from the Ajax calls, which I think is what your aiming to do.
I used bootstrap-tabs.js and it has worked perfectly.
But I didn't find information about how to load content through AJAX request.
So, how to use AJAX loading with bootstrap-tabs.js?
In Bootstrap 2.0 and up you have to bind to the 'show' event instead.
Here's an example HTML and JavaScript:
<div class="tabbable">
<ul class="nav nav-tabs" id="myTabs">
<li>Home</li>
<li>Foo</li>
<li><a href="#bar" data-toggle="tab">Bar</li>
</ul>
<div>
<div class="tab-pane active" id="home"></div>
<div class="tab-pane" id="foo"></div>
<div class="tab-pane" id="bar"></div>
</div>
</div>
JavaScript:
$(function() {
var baseURL = 'http://yourdomain.com/ajax/';
//load content for first tab and initialize
$('#home').load(baseURL+'home', function() {
$('#myTab').tab(); //initialize tabs
});
$('#myTab').bind('show', function(e) {
var pattern=/#.+/gi //use regex to get anchor(==selector)
var contentID = e.target.toString().match(pattern)[0]; //get anchor
//load content for selected tab
$(contentID).load(baseURL+contentID.replace('#',''), function(){
$('#myTab').tab(); //reinitialize tabs
});
});
});
I wrote a post about it here: http://www.mightywebdeveloper.com/coding/bootstrap-2-tabs-jquery-ajax-load-content/
You can listen the change event and ajax load content in the event handler
$('.tabs').bind('change', function (e) {
var now_tab = e.target // activated tab
// get the div's id
var divid = $(now_tab).attr('href').substr(1);
$.getJSON('xxx.php').success(function(data){
$("#"+divid).text(data.msg);
});
})
I wanted to load fully dynamic php pages into the tabs through Ajax.
For example, I wanted to have $_GET values in the links, based on which tab it was - this is useful if your tabs are dynamic, based on database data for example.
Couldn't find anything that worked with it but I did manage to write some jQuery that actually works and does what I'm looking for.
I'm a complete jQuery noob but here's how I did it.
I created a new 'data-toggle' option called tabajax (instead of just tab), this allows me to seperate what's ajax and what's static content.
I created a jQuery snippet that runs based on that data-toggle, it doesn't mess with the original code.
I can now load say url.php?value=x into my Bootstrap Tabs.
Feel free to use it if you want to, code is below
jQuery code:
$('[data-toggle="tabajax"]').click(function(e) {
e.preventDefault()
var loadurl = $(this).attr('href')
var targ = $(this).attr('data-target')
$.get(loadurl, function(data) {
$(targ).html(data)
});
$(this).tab('show')
});
HTML:
<li>Val 1</li>
So here you can see that I've changed the way bootstrap loads thing, I use the href for the dynamic ajaxlink and then add a 'data-target' value to the link instead, that should be your target div (tab-content).
So in your tab content section, you should then create an empty div called val1 for this example.
Empty Div (target):
<div class='tab-pane' id='val1'><!-- Ajax content will be loaded here--></div>
Hope this is useful to someone :)
I suggest to put the uri into the tab-pane elements, it allows to take advantage of web frameworks reverse url fonctionnalities. It also allows to depend exclusively on the markup
<ul class="nav nav-tabs" id="ajax_tabs">
<li class="active"><a data-toggle="tab" href="#ajax_login">Login</a></li>
<li><a data-toggle="tab" href="#ajax_registration">Registration</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="ajax_login"
data-target="{% url common.views.ajax_login %}"></div>
<div class="tab-pane" id="ajax_registration"
data-target="{% url common.views.ajax_registration %}"></div>
</div>
And here is the javascript
function show_tab(tab) {
if (!tab.html()) {
tab.load(tab.attr('data-target'));
}
}
function init_tabs() {
show_tab($('.tab-pane.active'));
$('a[data-toggle="tab"]').on('show', function(e) {
tab = $('#' + $(e.target).attr('href').substr(1));
show_tab(tab);
});
}
$(function () {
init_tabs();
});
I loads the active tab, and loads a tab only if it is not already loaded
There is an error in your code user1177811.
It has to be $('[data-toggle="tabajax"]').
Also there is room for improvement. The .load() method, unlike $.get(), allows us to specify a portion of the remote document to be inserted. So i added #content to load the content div of the remote page.
$this.tab('show'); is now only called, when response was a success.
Here is the code
$('[data-toggle="tabajax"]').click(function(e) {
e.preventDefault();
$this = $(this);
var loadurl = $(this).attr('href');
var targ = $(this).attr('data-target');
$(targ).load(loadurl+'?ajax=true #content', function(){
$this.tab('show');
});
});
Here is how I do it. I utilize an attribute data-href which holds the url I want to load on show. This will not reload data that is already loaded unless you set $('#tab').data('loaded'); to 0 or remove it. It also handles relative vs. absolute urls by detecting the location of the first slash. I am not sure of the compatibility with all browsers but it works in our situation and allows for the functionality we are looking for.
Javascript:
//Ajax tabs
$('.nav-tabs a[data-href][data-toggle="tab"]').on('show', function(e) {
var $this = $(this);
if ($this.data('loaded') != 1)
{
var firstSlash = $this.attr('data-href').indexOf('/');
var url = '';
if (firstSlash !== 0)
url = window.location.href + '/' + $this.attr('data-href');
else
url = $this.attr('data-href');
//Load the page
$($this.attr('href')).load(url, function(data) {
$this.data('loaded', 1);
});
}
});
HTML:
<div class="tabbable">
<ul class="nav nav-tabs">
<li class="active">
Tab 1
</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="js-tab1">
<p>
This content isn't used, but instead replaced with contents of tab1.php.
</p>
<p>
You can put a loader image in here if you want
</p>
</div>
</div>
</div>
Here is a solution I have found - and modified to suit my needs:
$("#tabletabs").tab(); // initialize tabs
$("#tabletabs").bind("show", function(e) {
var contentID = $(e.target).attr("data-target");
var contentURL = $(e.target).attr("href");
if (typeof(contentURL) != 'undefined') { // Check if URL exists
$(contentID).load(contentURL, function(){
$("#tabletabs").tab(); // reinitialize tabs
});
} else {
$(contentID).tab('show');
}
});
$('#tabletabs a:first').tab("show"); // Load and display content for first tab
});
This is an MVC example using Razor. It will interact with two partial views named: _SearchTab.cshtml and _SubmissionTab.cshtml
Notice that I am naming the id of the tabs the same as the partials.
Markup:
<!-- Nav tabs -->
<ul id="tabstrip" class="nav nav-tabs" role="tablist">
<li class="active">Submission</li>
<li>Search</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div class="tab-pane fade in active" id="_SubmissionTab">#Html.Partial("_SubmissionTab")</div>
<div class="tab-pane fade" id="_SearchTab"></div>
</div>
The #Html.Partial will request the page on the active tab on page load
Script:
<script>
$('#tabstrip a').click(function (e) {
e.preventDefault()
var tabID = $(this).attr("href").substr(1);
$("#" + tabID).load("/#ViewContext.RouteData.Values["controller"]/" + tabID)
$(this).tab('show')
})
</script>
The load function will perform an ajax request as each tab is clicked. As for what path is requested you will notice a #ViewContext.RouteData.Values["controller"] call. It simply gets the controller of the current view assuming the partial views are located there.
Controller:
public ActionResult _SubmissionTab()
{
return PartialView();
}
public ActionResult _SearchTab()
{
return PartialView();
}
The controller is needed to relay the load request to the proper partial view.
Here is the Bootstrap tab Ajax example, you can use it...
<ul class="nav nav-tabs tabs-up" id="friends">
<li> Contacts </li>
<li> Friends list</li>
<li>Awaiting request</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="contacts">
</div>
<div class="tab-pane" id="friends_list">
</div>
<div class="tab-pane urlbox span8" id="awaiting_request">
</div>
</div>
and here is the AJAX call
$('[data-toggle="tabajax"]').click(function(e) {
var $this = $(this),
loadurl = $this.attr('href'),
targ = $this.attr('data-target');
$.get(loadurl, function(data) {
$(targ).html(data);
});
$this.tab('show');
return false;
});
I use this function and it's really nice because she prevent's you from load ajax again when going back to that tab.
Tip: on tab href, just put the destination. Add this to footer:
$("#templates_tabs").tabs({
beforeLoad: function( event, ui ) {
if (ui.tab.data("loaded")) {
event.preventDefault();
return;
}
ui.ajaxSettings.cache = false,
ui.jqXHR.success(function() {
ui.tab.data( "loaded", true );
}),
ui.jqXHR.error(function () {
ui.panel.html(
"Not possible to load. Are you connected?");
});
}
});