I am new to alpacajs. I have alpacajs form and also have save button for alpacajs from. More than that i have previous and next button. I currently plan to develop something like below.
For example if someone come to the alpacajs form page and if they modified some fields in form then without save they can't allow to go previous/ next so i want to disable those button. If they save the form after the modification then they can go previous/ next so i want to enable those button.
How to do this with jquery and in alpacajs?
If you want to save the form data as draft form in your alpaca form you have only to add the Save as draft button next to your submit and put some logic to it.
So alpaca will handle the click event on that button, but not for Previous / Next buttons.
These buttons stays out of alpaca config, and they handle only page navigation.
To add a new button to your alpaca form
"form": {
"buttons": {
"save": {
"title": "Save draft",
"click": function() {
var value = this.getValue();
// call backend service to save the form as draft
$.ajax({
method: "POST",
url: "https://httpbin.org/post", // backend webservice
data: value // form data
})
.done(function(data) {
// check some backend response code or some flag
// with some conditions activate next and previous buttons
$("#previousBtn").prop('disabled', false);
$("#nextBtn").prop('disabled', false);
})
}
},
"submit": {
"click": function() {
var value = this.getValue();
alert(JSON.stringify(value, null, " "));
}
}
}
}
Don't forget to call some other webservice to get the draft data for that form if there's any and initialize alpaca data config like this:
// data initialization - here you can call a service to get draft data for this form
data = {
username: "test"
};
$("#form").alpaca({
"data": data, // draft data if there's any
"schema": {
// alpaca schema config
}
}
Here's a working fiddle for this.
Please, working sample code below. In this, Name and Feeback fields are marked as required and. Bydefault, Name field is filled, Feedback is empty which throws error and Submit button is disabled, As you type something in Feedback field, Submit button got enabled and form is beig allow to submit because all required fields got filled. Similarly, you can handle your form like this.
Hope this helps !!
<html>
<head>
<link type="text/css" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" />
<link type="text/css" href="//cdn.jsdelivr.net/npm/alpaca#1.5.27/dist/alpaca/bootstrap/alpaca.min.css" rel="stylesheet" />
<script type="text/javascript" src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.js"></script>
<script type="text/javascript" src="//cdn.jsdelivr.net/npm/alpaca#1.5.27/dist/alpaca/bootstrap/alpaca.min.js"></script>
</head>
<body>
<div id="form"></div>
<script type="text/javascript">
$(document).ready(function() {
$("#form").alpaca({
"data": {
"name": "Diego Maradona",
"ranking": "excellent"
},
"schema": {
"title": "User Feedback",
"description": "What do you think about Alpaca?",
"type": "object",
"properties": {
"name": {
"type": "string",
"title": "Name",
"required": true
},
"feedback": {
"type": "string",
"title": "Feedback",
"required": true
}
}
},
"options": {
"form": {
"attributes": {
"action": "http://httpbin.org/post",
"method": "post"
},
"buttons": {
"submit": {}
}
},
"fields": {
"name": {
"size": 20,
"helper": "Please enter your name."
},
"feedback": {
"type": "textarea",
"name": "your_feedback",
"rows": 5,
"cols": 40,
"helper": "Please enter your feedback."
}
}
},
"view": "bootstrap-edit"
});
});
</script>
</body>
</html>
I have a table using DataTables , it contains a large number of rows and so this causes the page to load very slowly as i assume the browser waits till the table is filled before displaying the page.
I would like to only load one page of the table (10 rows), and only show further data when the user browses through the table, showing a loading sign would be great too.
I have researched and heard of a DataTables function called 'deferRender' which is supposed to do what i need, but i can't get it to work with my table.
My table has 8 columns + the html is generated using PHP that builds the table from data in a text file:
<?php
$tdcount = 1; $numtd = 8; // number of cells per row
$str = "<table id=\"table1\" class=\"table1 table table-striped table-bordered\">
<thead>
<th>1</th>
<th>2</th>
<th>3</th>
<th>4</th>
<th>5</th>
<th>6</th>
<th>7</th>
<th>8</th>
</thead>
<tbody>
";
$f = fopen("tabledata.txt", "r");
if ( $f === FALSE ) {
exit;
}
while (!feof($f)) {
$arrM = explode(",",fgets($f));
$row = current ( $arrM );
if ($tdcount == 1)
$str .= "<tr>"; $str .= "<td>$row </td>";
if ($tdcount == $numtd) {
$str .= "</tr>";
$tdcount = 1;
} else {
$tdcount++;
}
}
if ($tdcount!= 1) {
while ($tdcount <= $numtd) {
$str .= "<td> </td>"; $tdcount++;
} $str .= "</tr>";
}
$str .= "</tbody></table>";
echo $str;
I then use the following code to turn it into a datatable:
<script>
$(document).ready(function() {
$('#table1').basictable({
forceResponsive: false
});
$('#table1').DataTable( { "order": [[ 0, "desc" ]] } );
});
</script>
I have read the instructions here: https://datatables.net/examples/server_side/defer_loading.html
and know i need to add parameters to the JS:
"processing": true,
"serverSide": true,
"ajax": "scripts/server_processing.php",
"deferLoading": 57
and use a server_processing script, however the example only shows how to use it when connecting to a DB, and not when the data is loaded from a text file with php.
How can i acheive this?
This will focus purely on the DataTables aspects of a "server-side" solution. How you write the server-side logic needed to support it is out of scope for this answer. But I hope these notes will at leasst clarify what that logic needs to be, and how you can approach it.
Assumptions
Assume you have a text file containing 1,000 rows of data like this (or a million - but too many rows to send to the browser and to DataTables, all at once). The text file is a simple pipe-delimited file, with three fields:
id|name|description
1|widget_1|This is a description for widget 1
2|widget_2|This is a description for widget 2
3|widget_3|This is a description for widget 3
...
1000|widget_1000|This is a description for widget 1000
You want to send 10 items at a time to DataTables, using server-side processing.
Your data maps to a simple JSON structure, like this - an array of objects (each object is one record):
[
{
"id": 1,
"name": "widget_1",
"description": "This is a description for widget 1"
},
{
"id": 2,
"name": "widget_2",
"description": "This is a description for widget 2"
},
... // more records...
]
The DataTable Definition
Your datatable definition looks like this - it is deliberately very simple, at this stage:
<body>
<div style="margin: 20px;">
<table id="demo" class="display dataTable cell-border" style="width:100%">
</table>
</div>
<script type="text/javascript">
$(document).ready(function() {
$('#demo').DataTable({
serverSide: true,
ajax: {
url: 'http://localhost:7000/data',
type: 'POST'
},
columns: [
{ title: 'ID',
data: 'id' },
{ title: 'Name',
data: 'name' },
{ title: 'Description',
data: 'description' }
]
});
});
</script>
</body>
Initial Response
When the web page is first displayed, it will send an initial POST request to the URL (http://localhost:7000/data), and it will expect to receive a JSON response from the web server, containing the data to be displayed.
Because DataTables is using serverSide: true, DataTables will expect the JSON to have a specific structure, as described here.
Specifically, the server has to add all of the mandatory fields (draw, recordsTotal, recordsFiltered, and data) to the JSON it sends to DataTables.
In our case it would look like this - note that it is just our previously mentioned JSON structure, with a few extra metadata fields added:
{
"draw": 1,
"recordsTotal": 1000,
"recordsFiltered": 1000,
"data": [{
"id": 1,
"name": "widget_1",
"description": "This is a description for widget 1"
}, {
"id": 2,
"name": "widget_2",
"description": "This is a description for widget 2"
}, {
"id": 3,
"name": "widget_3",
"description": "This is a description for widget 3"
}, {
"id": 4,
"name": "widget_4",
"description": "This is a description for widget 4"
}, {
"id": 5,
"name": "widget_5",
"description": "This is a description for widget 5"
}, {
"id": 6,
"name": "widget_6",
"description": "This is a description for widget 6"
}, {
"id": 7,
"name": "widget_7",
"description": "This is a description for widget 7"
}, {
"id": 8,
"name": "widget_8",
"description": "This is a description for widget 8"
}, {
"id": 9,
"name": "widget_9",
"description": "This is a description for widget 9"
}, {
"id": 10,
"name": "widget_10",
"description": "This is a description for widget 10"
}]
}
It is the server's responsibility to build this JSON - the first 10 records of the server's data set. The server also tells DataTables that it has a total of 1,000 records, and that it has not filtered out any data (yet) - hence there are also a total of 1,000 records after filtering.
DataTables needs all of this information, so it knows how many pagination buttons to display, and what pagination data to show.
Note that it is entirely the server's responsibility to do all this work - that's why it's called "server-side" processing.
The client (browser) only has 10 records to render - so that happens quickly.
(I just noticed that the screenshot mentions "500 records" - that's a mistake in my server-side code - there is no filter, so I need to fix that).
Subsequent Requests
When a user clicks on a page navigation button (e.g. page "4"), that triggers a new request from DataTables to the server. DataTables builds this request automatically, using the fields described here.
The request is sent as form data.
In our example, the request looks like this:
"Form data": {
"draw": "5",
"columns[0][data]": "id",
"columns[0][name]": "",
"columns[0][searchable]": "true",
"columns[0][orderable]": "true",
"columns[0][search][value]": "",
"columns[0][search][regex]": "false",
"columns[1][data]": "name",
"columns[1][name]": "",
"columns[1][searchable]": "true",
"columns[1][orderable]": "true",
"columns[1][search][value]": "",
"columns[1][search][regex]": "false",
"columns[2][data]": "description",
"columns[2][name]": "",
"columns[2][searchable]": "true",
"columns[2][orderable]": "true",
"columns[2][search][value]": "",
"columns[2][search][regex]": "false",
"order[0][column]": "1",
"order[0][dir]": "asc",
"start": "30",
"length": "10",
"search[value]": "",
"search[regex]": "false"
}
These fields tell the server everything it needs to know, so it can prepare the correct response.
In our case the most important fields are these:
"start": "30",
"length": "10"
Start at row 30, and provide 10 records.
It is, again, the server's responsibility to prepare a JSON response which accurately reflects the requested data.
In our case this means the server needs to have logic to read through the text file to the correct starting point (data row 31 - remember the offset starts at zero), and 10 rows in total (rows 31 through 40).
Other fields in the above request from DataTables describe how the data is to be sorted, and filtered. In our case there is no filter "search[value]": "", - and the data is to be sorted by the first column in ascending order.
Final Notes
I have deliberately not described the following:
1) How your server-side code handles the creation of the JSON responses it sends back to DataTables;
2) How your server-side code parses the form requests it receives from DataTables.
That all depends entirely on what your server-side technology is. DataTables doesn't care. It's just passing JSON messages - it is decoupled from the server-side implementation - as it should be.
Regarding the "defer render" option described here, that is an enhancement you may choose to add if you feel you need it. But I would recommend getting a more basic server-side implementation working first.
Not particulary relavant to any language, but I used Node.js as an example to make a minimum working project for what's explained above:
The data: (put this at the root of where you have the working directory of node.js service)
[ { "id": 1,
"name": "widget_1",
"description": "This is a description for widget 1"
},{ "id": 2,
"name": "widget_2",
"description": "This is a description for widget 2"
},{ "id": 3,
"name": "widget_3",
"description": "This is a description for widget 3"
},{ "id": 4,
"name": "widget_4",
"description": "This is a description for widget 4"
},{ "id": 5,
"name": "widget_5",
"description": "This is a description for widget 5"
},{ "id": 6,
"name": "widget_6",
"description": "This is a description for widget 6"
},{ "id": 7,
"name": "widget_7",
"description": "This is a description for widget 7"
},{ "id": 8,
"name": "widget_8",
"description": "This is a description for widget 8"
},{ "id": 9,
"name": "widget_9",
"description": "This is a description for widget 9"
},{ "id": 10,
"name": "widget_10",
"description": "This is a description for widget 10"
},{ "id": 11,
"name": "widget_11",
"description": "This is a description for widget 11"
},{ "id": 12,
"name": "widget_12",
"description": "This is a description for widget 12"
},{ "id": 13,
"name": "widget_13",
"description": "This is a description for widget 13"
},{ "id": 14,
"name": "widget_14",
"description": "This is a description for widget 14"
},{ "id": 15,
"name": "widget_15",
"description": "This is a description for widget 15"
},{ "id": 16,
"name": "widget_16",
"description": "This is a description for widget 16"
},{ "id": 17,
"name": "widget_17",
"description": "This is a description for widget 17"
},{ "id": 18,
"name": "widget_18",
"description": "This is a description for widget 18"
},{ "id": 19,
"name": "widget_19",
"description": "This is a description for widget 19"
},{
"id": 20,
"name": "widget_20",
"description": "This is a description for widget 20"
}]
The HTML: (put this under your working directory/public)
<!DOCTYPE html>
<html>
<body>
</head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.13.1/css/jquery.dataTables.css">
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.13.1/js/jquery.dataTables.js"></script>
</head>
<div style="margin: 20px;">
<div id = 'pageinfo' style='display:none'></div>
<table id="demo" class="display dataTable cell-border" style="width:100%"></table>
</div>
<script type="text/javascript">
$(document).ready(function() {
var table = $('#demo').DataTable({
serverSide: true,
ajax: {
url: 'http://localhost:3000/data',
data: $('#pageinfo').text(), //post pagination parameters to server
type: 'POST'
},
columns: [
{ title: 'ID',
data: 'id' },
{ title: 'Name',
data: 'name' },
{ title: 'Description',
data: 'description' }
],
lengthMenu: [5, 10, 20],
pageLength: 5
});
function getinfo(){
var info = table.page.info();
return info;
}
$('.dataTables_wrapper').on('click',function(e){
var info = table.page.info();
$('#pageinfo').text(JSON.stringify(info)) //get the pagination parameters
})
});
</script>
</body>
<html>
And the server:
const fs = require('fs');
const data = JSON.parse(fs.readFileSync("data.json", 'utf8'));
var express = require('express');
var app = express();
var bodyParser = require('body-parser')
app.use( bodyParser.json() ); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
app.use('/static', express.static(__dirname + '/public')); //directory for static html docs
app.post('/data', function(req, res){
var resp = {"recordsTotal": 20,"recordsFiltered": 20,"start":0,"length":5}
if(req.body.start){
resp.draw = JSON.parse(req.body.draw);
resp.data = data.slice(JSON.parse(req.body.start),
JSON.parse(req.body.start)+JSON.parse(req.body.length));
}else{
resp.draw = 1;
resp.data = data.slice(resp.start,resp.start+resp.length);
}
res.end(JSON.stringify(resp))
})
app.listen(3000, function () {
console.log('listening on port 3000');
});
Then you'd be able to just start the server, and browse the result at http://localhost:3000/static/dtable.html
Read through these codes, or probably dig in to a few intermediate outputs, and you'll have a better idea of how DataTable works under a minimum setup for server-side processing.
I have spent a couple of hours trying to figure out how to properly reset a form with token field on alpaca.js.
Not sure if this is a bug, or I am doing something wrong. I placed two reset buttons, a generic one and a second one that calls a function to reset the form.
<script type="text/javascript">
var value = {};
$("#myform").alpaca({
"schema": {
"title": "token field",
"type": "object",
"properties": {
"text_field": {"type": "text" },
"token_field": { "type": "token"},
}
},
"options": {
"fields": {
"text_field": {
"label": 'this is a text field',
"type": "text"
},
"token_field": {
"label": 'this is a token field',
"type": "token",
"tokenfield": {
},
},
},
"form": {
"buttons": {
"load": {
label:"load saved values",
"click": function() {
$('form#' + this.attributes.id)[0].reset();
this.setValue(value);
},
},
"reset": {},
"fancy_reset": {
"label": "reset with function",
"click": function() {
console.log(this.attributes.id);
$('form#' + this.attributes.id)[0].reset();
},
},
"save": {
label:"save",
"click":function(){
value = this.getValue();
console.log(this.getValue());
console.log(value);
},
},
},
},
},
});
</script>
Any insights on whats wrong here?
I've been working with Alpaca for year but I haven't use that type of and after some research I haven't found any solution in the Alpaca lib to reset that type of field, so I tried to use jquery and bootstrap tokenizer methods.
and I've came to this solution :
Create an eventlistener to the reset form event
$('form').on('reset', function(e) {
var control = $("#myform").alpaca("get");
var field = control.childrenByPropertyId['token_field'];
field.refresh();
});
In your load function after this.setValue(value) add this code:
if (typeof value.token_field != undefined) {
// getting Alpaca parent control (this holds everything)
var control = $("#myform").alpaca("get");
// get the token field
var field = control.childrenByPropertyId['token_field'];
// setting the saved token to the field using bs-tokenizer method setTokens
$(field.control).tokenfield('setTokens', value.token_field);
}
Here's a fiddle for that.
Tell me if you still have any issue.
I was playing few days with Webix, but I don't have enough experience with it, so need sme help.
What I need:
Create simple page with textarea and button. When I press button, it takes data entered in textarea and saves it in N's string in the data/data.php file.
This is what I could do so far:
<!DOCTYPE html>
<html>
<head>
<title>Loading from DB</title>
<link rel="stylesheet" href="C:/__OSS/00. Soft/Webix/codebase/webix.css" type="text/css">
<script src="C:/__OSS/00. Soft/Webix/codebase/webix.js" type="text/javascript"></script>
</head>
<body>
<!--<?php
$filename = getcwd() . "data/data.php";
echo $filename;
$line_i_am_looking_for = 5;
$lines = file( $filename , FILE_IGNORE_NEW_LINES );
$lines[$line_i_am_looking_for] = '6my modified line';
file_put_contents( $filename , implode( "\n", $lines ) );
?>-->
<div class='header_comment'>Test Button</div>
<div id="testB" style='height:600px'></div>
<hr>
<script type="text/javascript" charset="utf-8">
webix.ready(function(){
gridb = webix.ui({
container:"testB",
"view": "form",
"elements": [
{
"view": "textarea",
"name": "woNumber",
"id": "textarea",
"label": "",
"width": 300,
"height": 200,
"options": [
"onViewResize"
],
"value": "",
"placeholder": "WO number (separate with comma if several)",
"labelPosition": "top"
},
{
"view": "button",
"name": "getWODetails",
"label": "",
"value": "Submit",
"options": [
"autowidth:true"
],
on:{
onItemClick:function(id){
webix.message("Sikim BLEAT'!!!");
/* onItemClick: getTextareaData;
*/
}
},
"labelPosition": "top"
},
{
"view": "button",
"id": "button1",
"name": "getWODetails",
"label": "",
"value": "Passss",
"options": [
"autowidth:true"
],
on:{
onItemClick:function(){
webix.message("Values of textarea is "+$$('textarea').getValue());
}
},
"labelPosition": "top"
}
]
});
});
</script>
</body>
</html>
So I can get value from textarea with $$('textarea').getValue()), but have no idea how to write it in the file.
I can do it easily with PHP (commented out part) but don't know how to make it works with Webix. I believe it is not so hard, but can't figure out what to do..
Any help highly appreaciated.
I want to display data(json) in my site using AngularJs . here's what i did :
Create a database in phpmyAdmin .
Create a table with 2 row , subject and body . Should i create an id ?
After doing with PHP and angular , I got JSON like this :
[{
"0":"Soheil","subject":"Soheil",
"1":"Sadeghbayan","body":"Sadeghbayan"}
,{"0":"","subject":"","1":"","body":""}
,{"0":"","subject":"","1":"","body":""}
,{"0":"dasdasd","subject":"dasdasd","1":"qe","body":"qe"}
,{"0":"Hello","subject":"Hello","1":"This is chandler !","body":"This is chandler !"}
,{"0":"","subject":"","1":"","body":""},
{"0":"Something new in website","subject":"Something new in website","1":"oh Awsome !","body":"oh Awsome !"
}]
I think this is invalid JSON because when I replace it with custom JSON that I wrote it work .
Json valid
{
"fruits": [
{
"id": "1",
"name": "Apple"
},
{
"id": "2",
"name": "Orange"
}
]
}
AngularJS
var fruitsApp = angular.module('fruitsApp', []);
fruitsApp.factory('fruitsFactory', function($http) {
return {
getFruitsAsync: function(callback) {
$http.get('fruits.json').success(callback);
}
};
});
fruitsApp.controller('fruitsController', function($scope, fruitsFactory) {
fruitsFactory.getFruitsAsync(function(results) {
console.log('fruitsController async returned value');
$scope.fruits = results.fruits;
});
});
Html
<ul>
<li ng-repeat="fruit in fruits">
{{fruit.subject}} is {{fruit.body}}
</li>
</ul>
php
include('config.php');
$data = json_decode(file_get_contents("php://input"));
$subject = mysql_real_escape_string($data->subject);
$body = mysql_real_escape_string($data->body);
mysql_select_db("angular") or die(mysql_error());
mysql_query("INSERT INTO newstory (subject,body) VALUES ('$subject', '$body')");
Print "Your information has been successfully added to the database.";
$query = "SELECT * FROM newstory";
$result = mysql_query($query);
$arr = array();
while ($row = mysql_fetch_array($result)) {
$subject = $row['subject'];
$body = $row['body'];
$arr[] = $row;
}
echo json_encode($arr);
Any idea ? Thx in advance
Your JSON is a valid. Refer to this for information on JSON and this to check/validate a JSON object.
The data coming back from your $http.get / database data does not have a fruits attribute and you expect that when you set your $scope.fruits (the below snippet is taken from your code):
$scope.fruits = results.fruits;
The structure of the data that is being returned by the $http.get call is different than the format of your sample data.
Here's your $http.get / database data (I shortened it for brevity):
[
{
"0": "Soheil",
"1": "Sadeghbayan",
"subject": "Soheil",
"body": "Sadeghbayan"
},
{
"0": "Hello",
"1": "This is chandler !",
"subject": "Hello",
"body": "This is chandler !"
},
{
"0": "",
"1": "",
"subject": "",
"body": ""
}
]
And here's your sample / mock data:
{
"fruits": [
{
"id": "1",
"name": "Apple"
},
{
"id": "2",
"name": "Orange"
}
]
}
The former is an array of objects with keys: 0, 1, subject and body.
The latter is an object with keys: fruits.
They are both valid JSON objects with different object structures. But, you expect a fruits attribute where there isn't one. Also, your HTML/UI might be expecting the data format to look like what is in your mock data. So check that too.