I am new to react and trying to build a table component that changes based on what is passed in for headers and rows.
I have been following the fb react tutorials and I have hit a road block I have looked on here and did some changes but nothing is working.
Here is my HTML page that gets the generated content.
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset='utf-8'>
<meta http-equiv="X-UA-Compatible" content="IE=10; IE=9; IE=8; IE=7; IE=EDGE" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.4.1/css/bootstrap-datepicker3.css"/>
<link rel="stylesheet" type="text/css" href="/vendor/twbs/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="/vendor/etdsolutions/sweetalert/sweetalert.css?<?= assetCacheQueryStr() ?>" />
<link rel="stylesheet" type="text/css" href="/lib/jquery-ui-1.11.4/jquery-ui.css">
<link rel="stylesheet" type="text/css" media="screen" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.9.3/css/bootstrap-select.min.css">
<!-- Javascript -->
<script src="https://unpkg.com/react#15.3.2/dist/react.js"></script>
<script src="https://unpkg.com/react-dom#15.3.2/dist/react-dom.js"></script>
<script src="https://unpkg.com/babel-core#5.8.38/browser.min.js"></script>
<script src="https://unpkg.com/jquery#3.1.0/dist/jquery.min.js"></script>
<script src="https://unpkg.com/remarkable#1.6.2/dist/remarkable.min.js"></script>
<script src="/vendor/etdsolutions/sweetalert/sweetalert.min.js?<?= assetCacheQueryStr()?>"></script>
<script src="/vendor/twbs/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.9.3/js/bootstrap-select.min.js"></script>
<script src="/lib/sorttable.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.4.1/js/bootstrap-datepicker.min.js"></script>
<title>React</title>
</head>
<body>
<div id="loadboardContainer"></div>
<!-- Import the table react setup. -->
<script type="text/babel" src="test.js"></script>
</body>
</html>
Now I have the external react script in the test.js file which is this.
var Table = React.createClass({
getInitialState: function() {
return {
results: [],
columns: []
}
},
componentDidMount: function() {
this.serverRequest = $.get(this.props.source, function(result) {
result = JSON.parse(result);
this.setState({
results: result['resultRows'],
columns: $.makeArray(result['resultCols'])
});
}.bind(this));
},
componentWillUnmount: function(){
this.serverRequest.abort();
},
render: function() {
// Set array for rows.
var rows = [];
var header = [];
this.state.columns.map(function(cols) {
header.push(<TableColumns data={cols.cols} key={cols.id} />);
});
this.state.results.map(function(result) {
rows.push(<TableRow data={result.rows} key={result.id} />);
});
// Loop through head to get columns.
/*this.props.columns.forEach(function(cols) {
header.push(<TableColumns data={cols.cols} key={cols.id} />);
});
// Loop through the returned rows and display.
this.props.results.forEach(function(result) {
rows.push(<TableRow data={result.rows} key={result.id} />);
});*/
// Return the table.
return (
<table className="table table-condensed">
<thead>
{header}
</thead>
<tbody>
{rows}
</tbody>
</table>
);
}
});
// Set up columns
var TableColumns = React.createClass({
render: function() {
var colNodes = this.props.data.map(function(col, i){
return (
<th key={i}>{col}</th>
);
});
return (
<tr>
{colNodes}
</tr>
);
}
});
// Set up row
var TableRow = React.createClass({
render: function() {
var rowNodes = this.props.data.map(function(row, i){
return (
<td key={i}>{row}</td>
);
});
return (
<tr>
{rowNodes}
</tr>
);
}
});
var futureContainer = document.getElementById('loadboardContainer');
ReactDOM.render(<Table source="getTableValues.php" />, futureContainer);
As you can see I have the commented out part of what used to be the props calls to the table. Now that I am trying to get the information from another file it looks like on here I have to use state.
On the other file this is what I have. Its just an array of array to return data before I actually query the stuff.
<?php
// Start the session.
session_start();
// Set Variables.
$returned = array(); // Returns results
$returned['resultRows'][0] = array();
$returned['resultRows'][0]['id'] = 10221;
$returned['resultRows'][0]['rows'] = array("654221", "2016-03-26", "Customer 1", "98755/54622", "Carrier 1", "Driver 1", "2016-03-28", "TX - IN", "DRY", "1240", "", "", "This is a test note");
$returned['resultRows'][1] = array();
$returned['resultRows'][1]['id'] = 10223;
$returned['resultRows'][1]['rows'] = array("654221", "2016-03-26", "Customer 1", "98755/54622", "Carrier 2", "Driver 2", "2016-03-28", "TX - IN", "DRY", "1240", "", "", "This is a test note2");
$returned['resultCols']['id'] = 100;
$returned['resultCols']['cols'] = array("PO Number", "Load Date", "Customer(s)", "Customer PO", "Carrier", "Driver", "Delivery Date", "Lane", "Temp", "Weight", "Attention Date", "ND Date", "Notes");
echo json_encode($returned);
?>
I keep getting an error this.state.columns.map is not a function.
The same is true if I use this.props. So what am I doing wrong on this? I know how to make it work if I statically put in the data and insert that way on the since page but the call is not working.
You try to map a string at the beginning because of async $.get
replace this :
getInitialState: function() {
return {
results: '',
columns: ''
}
}
by this :
getInitialState: function() {
return {
results: [],
columns: []
}
}
EDIT TO MATCH PHP RETURN
var Table = React.createClass({
getInitialState: function() {
return {
results: [],
columns: []
}
},
componentDidMount: function() {
this.serverRequest = $.get(this.props.source, function(result) {
result = JSON.parse(result);
this.setState({
results: result['resultRows'],
columns: result['resultCols'].cols
});
}.bind(this));
},
componentWillUnmount: function(){
this.serverRequest.abort();
},
render: function() {
// Return the table.
return (
<table className="table table-condensed">
<thead>
<TableColumns data={this.state.columns} />
</thead>
<tbody>
{this.state.results.map(function(result) {
rows.push(<TableRow data={result.rows} key={result.id} />);
})}
</tbody>
</table>
);
}
});
// Set up columns
var TableColumns = React.createClass({
render: function() {
var colNodes = this.props.data.map(function(col, i){
return (
<th key={i}>{col}</th>
);
});
return (
<tr>
{colNodes}
</tr>
);
}
});
// Set up row
var TableRow = React.createClass({
render: function() {
var rowNodes = this.props.data.map(function(row, i){
return (
<td key={i}>{row}</td>
);
});
return (
<tr>
{rowNodes}
</tr>
);
}
});
var futureContainer = document.getElementById('loadboardContainer');
ReactDOM.render(<Table source="getTableValues.php" />, futureContainer);
Related
The pagination page numbers looks weird and lengthy. I want to display only some of the page numbers in frontend. my code It's working ok, but not good when there's large numbers of pages. so i'm using twbsPagination in function renderPagination. when i run my code i'm getting the error Uncaught TypeError: $(...).twbsPagination is not a function. twbsPagination source is script:src pagination.js. but when i run twbsPagination separate without any function it's working fine. how can i run twbsPagination with my code?
index.html
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css" integrity="sha512-+4zCK9k+qNFUR5X+cKL9EIR+ZOhtIloNl9GIKS57V1MyNsYpYcUrUeQc9vNfzsWfV28IaLL3i96P9sdNyeRssA==" crossorigin="anonymous" />
<script src="homer/vendor/jquery/dist/jquery.min.js"></script>
<script src="desk/vendor/pagination/pagination.min.js"></script>
<script src="desk/components/approved2.js"></script>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
</tr>
</thead>
<tbody id="approvedList">
</tbody>
</table>
<nav aria-label="Page navigation example">
<ul class="pagination"></ul>
</nav>
index.js
const localURL = "http://localhost:8000/"
// output Html
const Story = document.querySelector('#approvedList');
const pagination = document.querySelector('.pagination');
$(function () {
var page = 1,
records = 1,
totalRecords = 0,
search = '';
// Run on page load
fetchData();
setInterval(fetchData, 2000);
// data filtering
$("#search-input").keyup(function (e) {
let value = e.target.value
fetchData(search = value);
});
// Show Records limits
$("#records").click(function (e) {
let value = e.target.value
fetchData(records = value);
});
// Previous Page
$('[aria-label="Previous"]').click(function () {
if (page > 1) {
page--;
}
fetchData();
});
// Next page
$('[aria-label="Next"]').click(function () {
if (page * records < totalRecords) {
page++;
}
fetchData();
});
// data fetching from API
function fetchData() {
$.ajax({
url: "http://localhost:8000/api/approved/",
type: "GET",
data: {
page: page,
records: records,
search: search
},
success: function (res) {
totalRecords = res.count
Story.innerHTML = '';
res.results.map((object) => {
Story.innerHTML +=
`<tr>
<td> ` + object.id + `</td>
<td>${object.id}` + object.title + `</td>
</tr>`;
})
Pagination();
}
})
}
function Pagination() {
// let pagesNumbers = Math.ceil(totalRecords / records);
let pagesNumbers = Math.ceil(totalRecords / records);
$('#pagination').twbsPagination({
totalPages: pagesNumbers,
visiblePages: 5,
onPageClick: function (event, page) {
$('#page-content').text('Page ' + page);
}
});
}
})
You cannot add twice the jQuery library.
I don't know the pagination.min.js and approved2.js libraries but I know you can add the twbsPagination as follow:
<script src="https://cdnjs.cloudflare.com/ajax/libs/twbs-pagination/1.4.2/jquery.twbsPagination.min.js"></script>
Moreover, this line is wrong:
let pagesNumbers = Math.ceil(totalRecords / records);
pagesNumbers needs to be at least 1.
The snippet with your code:
const fakeData = {
data: [{
row: 1,
name: 'a'
}, {
row: 2,
name: 'b'
}, {
row: 3,
name: 'c'
}, {
row: 4,
name: 'd'
}, {
row: 5,
name: 'e'
}, {
row: 6,
name: 'f'
}, {
row: 7,
name: 'g'
}],
totalRecords: 7
};
// output Html
const Story = document.querySelector('#approvedList');
const pagination = document.querySelector('.pagination');
$(function () {
var page = 1,
records = 1,
totalRecords = 0,
search = '';
// Run on page load
fetchData();
// data fetching from API
function fetchData() {
totalCount = fakeData.totalCount;
Story.innerHTML = '';
fakeData.data.slice((page - 1) * records, page * records).map((object) => {
Story.innerHTML +=
`<tr >
<td>${object.row}</td>
<td>${object.name}</td>
</tr >
`;
})
renderPagination();
}
function renderPagination() {
let pagesNumbers = Math.ceil(totalRecords / records) || 1;
$('.pagination').twbsPagination({
totalPages: pagesNumbers,
visiblePages: 5,
onPageClick: function (event, page) {
$('#page-content').text('Page ' + page);
}
});
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/twbs-pagination/1.4.2/jquery.twbsPagination.min.js"></script>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
</tr>
</thead>
<tbody id="approvedList">
</tbody>
</table>
<nav aria-label="Page navigation example">
<ul class="pagination"></ul>
</nav>
I am getting a problem when trying to use DayPilot Calendar in angularjs.
https://code.daypilot.org/63034/angularjs-event-calendar-open-source
When I downloaded sources and use it it was not working and throwing error
angular.js:9563 TypeError: Cannot read property 'getTime' of undefined
at loadEvents (daypilot-all.min.js:11)
at update (daypilot-all.min.js:11)
at Object.fn (daypilot-all.min.js:11)
at h.$digest (angular.js:12031)
at h.$apply (angular.js:12279)
at g (angular.js:7991)
at C (angular.js:8196)
at XMLHttpRequest.y.onreadystatechange (angular.js:8137)
Source code of the downloaded code is
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>DayPilot: AngularJS Event Calendar</title>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
<script src="js/daypilot/daypilot-all.min.js" type="text/javascript"></script>
<!-- helper libraries -->
<script src="js/jquery/jquery-1.9.1.min.js" type="text/javascript"></script>
<!-- daypilot libraries -->
<script src="js/daypilot/daypilot-all.min.js" type="text/javascript"></script>
<link type="text/css" rel="stylesheet" href="media/layout.css" />
</head>
<body>
<div id="header">
<div class="bg-help">
<div class="inBox">
<hr class="hidden" />
</div>
</div>
</div>
<div class="shadow"></div>
<div class="hideSkipLink">
</div>
<div class="main">
<div ng-app="main" ng-controller="DemoCtrl" >
<div style="float:left; width: 160px">
<daypilot-navigator id="navi" daypilot-config="navigatorConfig" ></daypilot-navigator>
</div>
<div style="margin-left: 160px">
<div class="space">
<button ng-click="showDay()">Day</button>
<button ng-click="showWeek()">Week</button>
</div>
<daypilot-calendar id="day" daypilot-config="dayConfig" daypilot-events="events" ></daypilot-calendar>
<daypilot-calendar id="week" daypilot-config="weekConfig" daypilot-events="events" ></daypilot-calendar>
</div>
</div>
<script>
var app = angular.module('main', ['daypilot']).controller('DemoCtrl', function($scope, $timeout, $http) {
$scope.events = [];
$scope.navigatorConfig = {
selectMode: "day",
showMonths: 3,
skipMonths: 3,
onTimeRangeSelected: function(args) {
$scope.weekConfig.startDate = args.day;
$scope.dayConfig.startDate = args.day;
loadEvents();
}
};
$scope.dayConfig = {
viewType: "Day",
onTimeRangeSelected: function(args) {
var params = {
start: args.start.toString(),
end: args.end.toString(),
text: "New event"
};
$http.post("backend_create.php", params).success(function(data) {
$scope.events.push({
start: args.start,
end: args.end,
text: "New event",
id: data.id
});
});
},
onEventMove: function(args) {
var params = {
id: args.e.id(),
newStart: args.newStart.toString(),
newEnd: args.newEnd.toString()
};
$http.post("backend_move.php", params);
},
onEventResize: function(args) {
var params = {
id: args.e.id(),
newStart: args.newStart.toString(),
newEnd: args.newEnd.toString()
};
$http.post("backend_move.php", params);
},
onEventClick: function(args) {
var modal = new DayPilot.Modal({
onClosed: function(args) {
if (args.result) { // args.result is empty when modal is closed without submitting
loadEvents();
}
}
});
modal.showUrl("edit.php?id=" + args.e.id());
}
};
$scope.weekConfig = {
visible: false,
viewType: "Week",
onTimeRangeSelected: function(args) {
var params = {
start: args.start.toString(),
end: args.end.toString(),
text: "New event"
};
$http.post("backend_create.php", params).success(function(data) {
$scope.events.push({
start: args.start,
end: args.end,
text: "New event",
id: data.id
});
});
},
onEventMove: function(args) {
var params = {
id: args.e.id(),
newStart: args.newStart.toString(),
newEnd: args.newEnd.toString()
};
$http.post("backend_move.php", params);
},
onEventResize: function(args) {
var params = {
id: args.e.id(),
newStart: args.newStart.toString(),
newEnd: args.newEnd.toString()
};
$http.post("backend_move.php", params);
},
onEventClick: function(args) {
var modal = new DayPilot.Modal({
onClosed: function(args) {
if (args.result) { // args.result is empty when modal is closed without submitting
loadEvents();
}
}
});
modal.showUrl("edit.php?id=" + args.e.id());
}
};
$scope.showDay = function() {
$scope.dayConfig.visible = true;
$scope.weekConfig.visible = false;
$scope.navigatorConfig.selectMode = "day";
};
$scope.showWeek = function() {
$scope.dayConfig.visible = false;
$scope.weekConfig.visible = true;
$scope.navigatorConfig.selectMode = "week";
};
loadEvents();
function loadEvents() {
// using $timeout to make sure all changes are applied before reading visibleStart() and visibleEnd()
$timeout(function() {
var params = {
start: $scope.week.visibleStart().toString(),
end: $scope.week.visibleEnd().toString()
}
$http.post("backend_events.php", params).success(function(data) {
$scope.events = data;
});
});
}
});
</script>
</div>
<div class="clear">
</div>
</body>
</html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
i am still confused why this problem is occurring again and again
You should check the response returned by "backend_events.php". DayPilot expects an array of events in JSON format. If there is any server-side error in the script the response will return an error message instead.
Most likely, there is a problem with permissions on the server side - the PHP script needs read/write permissions for daypilot.sqlite file which is in the application root.
I am making a table
HTML tag
<table id="example" class="display" onload="callData()"></table>
javascript
function dataIsSet(){
var dataSet=[];
syncAjaxCall("POST","getGridData" ,"", "application/json")
.done(
function(data) {
if(data.response.Status==1){
for(i=0;i<data.response.Result.length; i++){
dataSet.push([])
}
for(i=0;i<data.response.Result.length; i++){
dataSet[i].push(data.response.Result[i].interestsName);
dataSet[i].push(data.response.Result[i].subscriberCount);
dataSet[i].push(data.response.Result[i].messageCount);
}
}
else
showMessage("green", data.response.Description, "");
});
if (dataSet[0].length==3)
return dataSet;
}
function callData() {
debugger;
$('#example').DataTable( {
data: dataIsSet(),
columns: [
{ title: "Interest Name" },
{ title: "No of Subscribers" },
{ title: "No of Messages" }
] ,
} );
}
My javascript file
<script src="interests/js/jquery-1.12.0.min.js" type="text/javascript"> </script>
<script src="interests/js/jquery.dataTables.min.js" type="text/javascript"></script>
My css file
<link rel="stylesheet" type="text/css" href="interests/css/jquery.dataTables.min.css"/>
Now I want to make no. of messages column a link where it will take value from interest name.
Just insert them inside of PutItHeretag buddy.
On adding ko validation extender to dynamic objects it is not displaying the error message when showAllMessages() is called. There is also no span tag added below the respective controls which will show the error message.
I also like to show the error message just below the control as soon as the object is added to observable array.
Please find the fiddle
http://plnkr.co/edit/PUgxqrarDeaabDxUwgLO?p=preview
JavaScript
var schedule = function() {
var self = this;
self.name = ko.observable();
self.startDate = ko.observable();
self.endDate = ko.observable();
// Add validation
self.name.extend({required: {message: 'Name Required'}});
self.startDate.extend({required: {message: 'Start Date Required'}});
self.endDate.extend({required: {message: 'End Date Required'}});
}
var viewmodel = {
model: {
lookups: {
grandSlams: ["Australian Open", "French Open", "Wimbledon", "US Open"]
},
schedules: ko.observableArray(),
status: ko.observable()
},
actions: {
addSchedule: function() {
console.log('Add Called');
viewmodel.model.schedules.push(new schedule());
viewmodel.model.status('Edited');
console.log(viewmodel.model.schedules().length);
},
saveSchedule: function(){
console.log('Save Called');
var errors = ko.validation.group(viewmodel.model.schedules, { deep: true });
if (errors().length > 0) {
console.log(errors());
errors.showAllMessages();
hasError = true;
}
viewmodel.model.status('Saved!!!');
}
}
};
$(function() {
ko.validation.init({
insertMessages: true,
messagesOnModified: true,
grouping: {
deep: true, //by default grouping is shallow
observable: true //and using observables
}
});
ko.applyBindings(viewmodel);
});
HTML
<!DOCTYPE html>
<html>
<head>
<script data-require="jquery#*" data-semver="2.1.4" src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script data-require="knockout#2.2.1" data-semver="2.2.1" src="//cdnjs.cloudflare.com/ajax/libs/knockout/2.2.1/knockout-min.js"></script>
<script data-require="knockout-validation#*" data-semver="1.0.2" src="//cdnjs.cloudflare.com/ajax/libs/knockout-validation/1.0.2/knockout.validation.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<h1>Knockout Validation!</h1>
<button data-bind="click: actions.addSchedule">Add Schedule</button>
<button data-bind="click: actions.saveSchedule">Save Schedule</button>
<h3>Schedules</h3>
<table>
<thead>
<tr>
<th>Grand Slams</th>
<th>Start</th>
<th>End</th>
</tr>
</thead>
<tbody data-bind="foreach:model.schedules">
<tr>
<td style="width:250px">
<select data-bind="options: $root.model.lookups.grandSlams, optionsCaption:'Select...'"></select>
</td>
<td style="width:250px">
<input type="text" data-bind="value: startDate" />
</td>
<td style="width:250px">
<input type="text" data-bind="value: endDate" />
</td>
</tr>
</tbody>
</table>
<h3 data-bind="text: model.status"></h3>
</body>
</html>
Updated example
You're missing the value binding on the select element. It should be
<select data-bind="value: name, options: $root.model.lookups.grandSlams, optionsCaption:'Select...'"></select>
Updated viewmodel if you want to validate on addSchedule (you can probably remove this.actions.showErrors() from save now, I left it just in case)
var viewmodel = {
model: {
lookups: {
grandSlams: ["Australian Open", "French Open", "Wimbledon", "US Open"]
},
schedules: ko.observableArray(),
status: ko.observable()
},
actions: {
addSchedule: function() {
console.log('Add Called');
viewmodel.model.schedules.push(new schedule());
viewmodel.model.status('Edited');
this.actions.showErrors();
console.log(viewmodel.model.schedules().length);
},
showErrors: function() {
var errors = ko.validation.group(viewmodel.model.schedules, { deep: true });
if (errors().length > 0) {
console.log(errors());
errors.showAllMessages();
hasError = true;
}
},
saveSchedule: function(){
console.log('Save Called');
var errors = ko.validation.group(viewmodel.model.schedules, { deep: true });
this.actions.showErrors();
viewmodel.model.status('Saved!!!');
}
}
};
index.html
<html>
<head>
<meta charset="utf-8" />
<meta name="format-detection" content="telephone=no" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="js/lib/bootstrap/css/bootstrap.min.css" rel="stylesheet" media="screen">
<link href="js/lib/bootstrap/css/bootstrap-responsive.css" rel="stylesheet">
<link href="js/lib/ratchet/ratchet-theme-ios.css" rel="stylesheet">
<link href="js/lib/ratchet/ratchet.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="css/index.css" />
<title>totter</title>
</head>
<body>
<div class="content">
</div>
<script src="js/lib/jquery-1.9.1.min.js"></script>
<script src="js/lib/underscore-min.js"></script>
<script src="js/lib/backbone-min.js"></script>
<script src="js/lib/bootstrap/js/bootstrap.js"></script>
<script src="js/lib/handlebars/handlebars-v1.3.0.js"></script>
<script src="js/lib/ratchet/ratchet.js"></script>
<script src="js/common/helper.js"></script>
<script src="js/app.js"></script>
<script src="js/views/home.js"></script>
<script src="js/views/signin.js"></script>
<script src="js/models/home.js"></script>
<script src="js/models/signin.js"></script>
</body>
</html>
app.js
var app = {
views: {},
models: {},
loadTemplates: function(views, callback) {
var deferreds = [];
$.each(views, function(index, view) {
if (app[view]) {
deferreds.push($.get('template/' + view + '.hbs', function(data) {
app[view].prototype.template = _.template(data);
}, 'html'));
} else {
alert(view + " not found");
}
});
$.when.apply(null, deferreds).done(callback);
}
};
app.Router = Backbone.Router.extend({
routes: {
"": "home",
"signIn":"SignIn"
},
home: function () {
// Since the home view never changes, we instantiate it and render it only once
if (!app.home) {
app.home = new app.HomeView();
app.home.render();
} else {
// delegate events when the view is recycled
app.home.delegateEvents();
}
},
SignIn:function(){
if (!app.signin) {
app.signin = new app.SignInView();
app.signIn.render();
} else {
// delegate events when the view is recycled
app.signin.delegateEvents();
}
}
});
$(document).on("ready", function () {
app.loadTemplates(["HomeView"],
function () {
app.router = new app.Router();
Backbone.history.start();
});
});
home.js
app.HomeView = Backbone.View.extend({
//Calling the render method to render view from the template
initialize:function(){
this.render();
},
//Pass the handlebars template for complilation and
render: function () {
var path = './template/HomeView.hbs';
Helper.GET_TEMPLATE(path, function(template) {
//pass collection to template to set values
var html = template(app.homeCollection.toJSON());
//pass collection to template to set values
$('.content').html(html);
});
$('.signin').bind('click', function(e) {
app.Router.navigate("signIn", {trigger: true});
});
}
});
app.home = new app.HomeView();
sigin.js
app.SigInView = Backbone.View.extend({
//Calling the render method to render view from the template
initialize:function(){
this.render();
},
//Pass the handlebars template for complilation and
render: function () {
var path = './template/SignInView.hbs';
Helper.GET_TEMPLATE(path, function(template) {
//pass collection to template to set values
var html = template(app.signinCollection.toJSON());
//pass collection to template to set values
$('.content').html(html);
});
}
});
app.signin = new app.SigInView();
helper.js
var Helper = {};
Helper.GET_TEMPLATE = function(path,callback){
var source, template;
$.ajax({
url: path,
success: function(data) {
source = data;
//Compile the raw data we got from the file
template = Handlebars.compile(source);
//execute the callback if passed
if (callback){
callback(template);
}
}
});
}
homeModel.js
var HomeModel = Backbone.Model.extend();
var homeData = new HomeModel({
id: 1,
signUpTitle: 'Sign Up for TOT ',
signInTitle: 'Sign In',
slogan:'slogan slogan slogan slogan slogan slogan slogan slogan slogan slogan '
});
/**
* Defining a Collection to set model
*/
var HomeCollection = Backbone.Collection.extend({
model: HomeModel
});
/**
* Defining a array to hold the collection
*/
app.homeCollection = new HomeCollection([homeData]);
HomeView.hbs
<header class="bar bar-nav">
<h1 class="title">totter</h1>
</header>
<div class="logo">
<img src = "img/choice.png">
</div>
{{#each []}}
<div class="textcontent">
<label>{{this.slogan}}</label>
</div>
<div class="footer">
<button class="btn btn-primary btn-block signup" style="">{{this.signUpTitle}}</button>
</div>
<div class="footer">
<button class="btn btn-primary btn-block signin">{{this.signInTitle}}</button>
</div>
{{/each}}
In the above code I used to develop a simple app with 2 views. I want to show sign-in view on button click of sign-in.
How can I achive this? I am using "handlebars" and "backbone.js".
The events aren't firing because you're utilizing the View el property. Either give it a preexisting element or insert the el itself to the DOM.
see the answer on the following discussion for a more comprehensive explanation.