I apologize for the newbie question but I am getting conflicting answers to this while searching on the net.
I have created an AngularJS app to read from a JSON file using $http.get and display the data as a form with each form element binded with ng-model. Ideally I would like the user to be able to edit the desired field and click save, then have that data updated in the JSON file. I have been told that to do this you will need a 3rd party server like NodeJS, but I am seeing other examples that show it being done in videos. Can someone tell me if this is possible without the 3rd party server and if so what is the best practice for doing this.
Thank you
$http GET (for resource located on client) will not work with the Chrome browser and will give a CORS error (unless you disable Chrome web security by opening Chrome using run .../chrome.exe" --allow-file-access-from-files -disable-web-security). Firefox gives an error saying the JSON in not well formed even though it is. Browsers don't seem to like it.
HTML5 LocalStorage is your best bet for client storage where you wish to perform CRUD operations and have the data survive past page refresh. A good example of this is the [TodoMVC example]
(https://github.com/tastejs/todomvc/tree/gh-pages/architecture-examples/angularjs)
A very simple example that saves a json file to localstorage and reads the contents of localstorage is shown. The Service contains a getter and a setter method to interact with localstorage.
INDEX.HTML
<body ng-app = "app">
<div ng-controller="MainCtrl">
<form>
<input placeholder="Enter Name.." ng-model="newContact"/>
<button type="submit" class="btn btn-primary btn-lg"
ng-click="addContact(newContact)">Add
</button>
</form>
<div ng-repeat="contact in contacts track by $index">
{{contact.name}}
</div>
</div>
APP.JS
angular.module('app', ['app.services'] )
.controller('MainCtrl', function ($scope, html5LocalStorage) {
//create variable to hold the JSON
var contacts = $scope.contacts = html5LocalStorage.get();
$scope.addContact = function(contact) {
$scope.contacts.push( {"name":contact} ); //Add new value
html5LocalStorage.put($scope.contacts); //save contacts to local storeage
}
});
SERVICES.JS
angular.module('app.services', [] )
.factory('html5LocalStorage', function () {
var STORAGE_ID = 'localStorageWith_nG_KEY'; //the Local storage Key
return {
//Get the localstorage value
get: function ()
{
return JSON.parse(localStorage.getItem(STORAGE_ID) || '[]');
},
//Set the localstorage Value
put: function (values)
{
localStorage.setItem(STORAGE_ID, JSON.stringify(values));
}
};
});
Otherwise you could use Node and Express and store the JSON file on the server. Use file system module 'fs-extra' to interact with the json file.
You would have to create RESTful API routes for the client to interact with the server using $http and perform CRUD operations.
/put
/get
/delete
/post
I would be interested to see these videos of this being done without the server writing to the file. You cant just "post the .json file" and have it replace the old one, unless you configure your server (apache, nginx, tomcat, node) to do so.
Related
Can I dynamically edit the url of the datatable depending on the value of the “Value” field of the search form in another file?
For example:
{ view:"text", label:"input data", value:"apple" }
In datatable.js
url: 'resource->/api/archive/apple'
Okay, I was told that I can send AJAX requests, but now I can't figure out how to get them correctly on another page
Sending:
webix.ajax().post('apples', get_form())
routie('apples')
In devtools I get the form value
I'm trying to get the formData value to substitute it in the URL
function get_data() {
let result;
webix.ajax("apples").then(function (data) {
data = data.text();
result = data;
});
return result;
}
URL
url: 'resource->/api/archive/all/'.concat(get_data()),
On the backend side, this controller works well, but I can't call it from the front side. I'm just learning frontend, so any help would be greatly appreciated.
In general, the way to do this is: When the value is changed (the onChange event), call clearAll() and load(newUrl) methods of the datatable. You cannot change the url property at runtime (well, you can, but it won't work).
As for different files, people usually build SPAs with Webix, so files here might be modules, not pages. Do you use Webix Jet? If yes, then communication between the form and the datatable can be done via the app event bus. If not, then they can communicate directly (import both files in some other file and do it there). If this is a multiple-page app, then yes, you do need some server side communication between them (maybe even with sockets).
For a custom AngularJS application that uses data from an API I've been creating I've come across the use of Angular oboe. Oboe is a bower package that helps streaming large JSON files to the view. So after some trial and error, I've managed to build a decent oboe GET method that obtains around 4000 JSON items in around 2 seconds. But my problem starts when adding more GET methods to the same view.
At first there weren't any problems but eventually, the loading time keeps getting bigger and bigger. So I've tried using the Oboe Cached: true configuration. Sadly it doesn't work at all. Every time I load the page all the data is loaded again instead of obtained from the browser Cache
In my example below, you're able to see the structure of one of my oboe function's that I've been trying to cache. A JSfiddle link is added down below as well.
The Function and the view
function createProduct(id, name) {
this.id = id;
this.name = name;
}
$scope.products = [];
oboe({
url: 'config/get/getProducts.php',
method: 'GET',
cached: true
}).path('products.product.*', function () {
// we don't have the person's details yet but we know we
// found someone in the json stream. We can eagerly put
// their div to the page and then fill it with whatever
// other data we find:
}).start(function () {
console.log("start");
}).node('products.product.*', function (products) {
// we just found out their name, lets add it
// to their div:
$scope.products.push({
id: products.id,
name: products.name.language
});
$scope.totalItems = $scope.products.length;
return new createProduct(products.id, products.name);
}).done(function () {
console.log( $scope.products );
});
// Refresh data
$scope.refreshData = function() {
cartService.refreshData()
.then(function(response) {
$scope.cartItems = response.cartItems;
$scope.totalCartItems = response;
$scope.selectedCustomer = response;
})
};
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="productimg col-lg-4 col-md-4" ng-repeat="product in products | limitTo : limit : (currentPage - 1) * limit track by product.id"
ng-class="{lastItem: $last}" scroll-bottom="event">
<div class="row">
<div class="col-md-12" ng-bind="product.id"></div>
<div class="col-md-12">
<a ng-bind="product.name" href="{{product.id}}.nl"></a>
</div>
</div>
</div>
<div class="col-lg-12 text-center margin-t-30">
<ul uib-pagination
total-items="totalItems"
ng-model="currentPage"
items-per-page="limit">
</ul>
</div>
In the JSfiddle You're able to see the code. I couldn't get the JSON to work on on JSfiddle but see it as the following line but then around 10000 "product" rows.
{"products":{"product":[{"id":"1240","id_manufacturer":"0","id_supplier":"0","id_category_default":"2","id_tax_rules_group":"8","quantity":"0","id_shop_default":"1","reference":{},"ean13":"0","price":"0.000000","active":"0","date_add":"2014-07-15 12:06:34","date_upd":"2018-04-21 12:22:37","name":{"language":"zie voorschot factuur 03"}},{"id":"1241","id_manufacturer":"0","id_supplier":"0","id_category_default":"2","id_tax_rules_group":"8","quantity":"0","id_shop_default":"1","reference":{},"ean13":"0","price":"0.000000","active":"0","date_add":"2014-07-15 12:06:41","date_upd":"2018-04-21 12:22:37","name":{"language":"zie voorschot factuur 04"}},{"id":"8908","id_manufacturer":"0","id_supplier":"15","id_category_default":"2","id_tax_rules_group":"8","quantity":"0","id_shop_default":"1","reference":"041002","ean13":"5712084210057","price":"45.454545","active":"1","date_add":"2015-11-12 18:03:47","date_upd":"2017-11-18 09:57:27","name":{"language":"Vaavud Sleipnir smartphone wind meter"}}}}
So the real struggle I'm facing is that getting the data from the network tab takes around ten seconds. (there is an API request at "getProducts.php"). Then parsing that to the view costs around 30 seconds. (way too long). Secondly, I would like to cache the getProducts request so that the products are directly obtained the next time the view is loaded. With a normal $http.get() and cache: true. It worked but then I'm still facing the slow binding, even with Oboe.
If there is any more information needed please let me know in the comments below.
As always, thanks in advance!
We had a project like this which had too much API with heavy object data. Some of tips we used are these:
1-Arrays instead of Objects
With a bit searching and reading about these data structures, you'll find that the memory consumed by objects is more than the memory used by Arrays. So convert your Array of objects to array of arrays in server side.
2-Use one more level cache
Store data in a server side cache, something like MongoDb and Redis. Handle requests with these steps:
Check the browser cache. If data is available and up-to-date, use this data.
If data is not available in browser, send request to server. Check the server side cache. If data is available and up-to-date, Send this data to client and store it in cache and also use it.
If data is not available in server cache, Send request to API and get data, Store it in server cache, and then sent it back to client and store it in cache and also use it.
3-Send minimum data required by client each time
A client may not stay in a page and see all data shown. Prepare minimum data you need for each page and if client request, bring the others.
For your case, instead of 10,000 product, Just prepare 1000 of them for example and if client needs more, prepare more data, append to your client cache and show it.
If all 10,000 products are required by client, prepare them in several requests.
Read more here
4-Cache data in browser with good module and in correct way for reading data again
There are some modules prepared for AngularJs. Read about them, their standards and best practices. This is so important to have a good client cache.
ngStorage
Hope these tips help you.
I have a file with 10 variables stored in it, locally on my system. I want this to be available to someone else when they connect to my system. This will be used within my LAN only and not over the internet so there is no need to worry about security. I want to create a simple client-server application that uses HTTP request/response to communicate.
I can work with HTML and Javascript but I have limited knowledge of Node JS. I have created a HTML page with 10 blank labels and a "show" button. When I click on the button, I want the file to be read and each of the 10 variables to be displayed in the labels.
Here is a sample with two variables and a button.
**index.html**
<html>
<body>
<form method="post" action="/">
<fieldset>
<legend><h2>Parameters:</h2></legend>
System ID : <textarea name="my_id" id="my_id" size="2"></textarea><br >
System IP : <textarea name="my_ip" id="my_ip" size="15"></textarea><br>
<input id="show" type="submit" name="show" value="SHOW"><br>
</fieldset>
</form>
</body>
</html>
How do I go about this? Is there any easier way besides Node JS ?
If this works I would also like to over-write the variables in the same file with the user's inputs (using a different "submit" button).
I would recommend just using the http module along with the fs module for this but since you are still learning nodejs, I would recommend expressjs and flat-file-database
So when you are creating routes for your small webapp, it would probably look like this :
// Serves html file
app.get('/', function(req, res) {
res.sendFile('/index.html');
});
// Stores data from the form
app.post('/form', function(req, res) {
var data = req.body;
db.put('data', data); // Saves data to the flat file db
res.status(201);
});
// Gets data from the db
app.get('/form', function(req, res) {
var data = db.get('data');
res.status(200).json(data);
});
You would need to 'post' the data at /form in your client side code.
To get the data, simply issue a get request at /form
Also keep in mind that for express to parse form data, you need the body-parser middleware.
Oh and note that I have no idea whether flat-file db is asyncronous or not so you will probably need to check that yourself.
I'm attempting to create a simple guestbook with AngularJS, and read and write the names to a simple file. Trouble is, I can't seem to get my code to even read from the file.
This is my directory structure:
This is index.html:
<!DOCTYPE html>
<html ng-app>
<head>
<meta charset="ISO-8859-1">
<title>GuestBook</title>
<script src="http://code.angularjs.org/angular-1.0.0rc3.min.js"></script>
<script type="text/javascript" src="javascript/user.js"></script>
</head>
<body>
<h1>Welcome!</h1>
<div ng-controller="UserCtrl">
<ul class="unstyled">
<li ng-repeat="user in users">
{{user}}
</li>
</ul>
</div>
</body>
</html>
This is user.js (Based off this question/answer):
function UserCtrl($scope) {
$scope.users = $(function() {
$.get('data/users', function(data) {
var array = data.split(',');
console.log(array);
});
});
}
And this is my users file:
John,Jacob,James
I'm expecting this outcome:
Welcome!
John
Jacob
James
But instead, all I get is:
Welcome!
So my question is, how can I populate $scope.users with the names in the users file?
I know I've got my AngularJS set up correctly because I was able to get the desired result when I hard-coded it:
$scope.users =[John,Jacob,James];
I've also spent a lot of time googling and searching Stack Overflow for how to read and write to a file with JavaScript and/or AngularJS, but:
No one seems to be trying to do exactly what I'm trying to do;The instructions are either confusing or not really applicable to what I'm trying to do.
I'm also not sure where to begin to write code that will persist names to the users file -- but I'll be happy if I can just read the file for now, and ask how to write to it later in a separate question. (But extra gratitude if you do also show me how to write to it.)
Try injecting angular's $http service into your controller first of all. And make sure you add a '/' before your 'data/users' path. (/data/users)
function UserCtrl($scope, $http) {
$scope.users = [];
$http.get('/data/users')
.success(function(data, status, headers, config) {
if (data && status === 200) {
$scope.users = data.split(',');
console.log($scope.users);
}
});
});
}
You can check your console to see what kind of data is being returned. (Network tab)
edit: just realized the $(function ... part didn't make sense.
The problem with your code is in this stub -
$scope.users = $(function() {
$.get('data/users', function(data) {
var array = data.split(',');
console.log(array);
});
});
Here $scope.users is not the array variable. Instead, it is whatever $() returns.
Your anonymous function is passed only as a parameter to $ function.
Rewrite your controller this way -
function UserCtrl($scope, $http) {
$scope.users = [] // Initialize with an empty array
$http.get('data/users').success(function(data, status, headers, config) {
// When the request is successful, add value to $scope.users
$scope.users = data.split(',')
})
}
And now, since you have
<li ng-repeat="user in users">
{{user}}
</li>
in your view, angular will set up a watch on $scope.users variable.
If the value of $scope.users changes anytime in the future, angular will automatically
update the view.
EDIT -
Along with the above edit, you need to make sure all the files are being served via a web server on the same host:port. Browsers limit AJAX access to another domain:port. Here is a quick way to do start a http server -
Go to the project directory using terminal and type in
python -m SimpleHTTPServer for python
or
ruby -run -e httpd -- -p 8000 . for ruby.
Both will start a basic HTTP server at port 8000, serving content from that particular directory. Having done this, your index.html will be at http://localhost:8000/index.html and your data file should be accessibe as http://localhost:8000/data/user.js (your javascript can still use /data/user.js).
It turns out I can't do what I'm trying to do the way I'm trying to do it. JavaScript by itself can't read files on the Server-Side, only on the Client-Side. To read and persist data, JavaScript has to make calls to a "Back-end" or server, written in something like Java, which isn't just a Browser scripting language.
you entered 'users' instead of 'users.txt' as filename.
This works just fine to me:
function UserCtrl($scope, $http) {
$scope.users = []
$http.get('data/users.txt').success(function(data, status, headers, config) {
$scope.users = data.split(',')
})}
i'm quite new to javascript/jQuery/Json. i'm building myself a local app ( no client side for now). right now i have a simple form (inputs and submit) and would like to get the inputs from the user with javascrip/JQuery and then build a JSON object and store it on a file. i managed to get the inputs using jQuery ,and using JSON.strigify() i have a JSON object. only thing is that i dont know how to write to a file with JS. i searched for a solution and understand that i might need to use PHP for that as JS is not meant for changing files.
here is my code:
HTML form:
<form name="portfolio" id="portfolio" method="post" onsubmit="getform()">
<p>General</p>
Portfolio Name: <input type="text" id="portfolioName" name="portfolioName"><br>
Owner First Name: <input type="text" id="ownerFName" name="ownerFName"><br>
Owner Last Name: <input type="text" id="ownerLName" name="ownerLName"><br>
<p>Risk Management</p>
%stocks : <input type="text" id="stocksPerc" name="stocksPerc"><br>
<input type="submit" value="submit">
</form>
JS code
function getform() {
var portfolioName = document.portfolio.portfolioName.value;
var ownerFname = document.portfolio.ownerFName.value;
var ownerLname = document.portfolio.ownerLName.value;
var stocksPerc = document.portfolio.stocksPerc.value;
var myJsonObject =JSON.stringify({
"general": {
"portfolioName": portfolioName,
"ownerFname": ownerFname,
"ownerLname": ownerLname
},
"riskManagement": {
"stocksPerc": stocksPerc
}
});
alert(myJsonObject);
event.preventDefault();
};
now in "myJsonObject" i have the JSON object which i would like to write to a local file.
later on i would like to read this file ,and maybe update some of the values there.
can someone please help me understand how do i write it to a file ?
you can try and load this page which runs my code. hope it works for you.
note: programming is my area of interest but i didnt study it ,i'm learning all by myself so i'm sorry if i askqdo things that make you blind for a moment :). also this is the first question i post here ,feel free to say if i need to improve.
Thanks
Sivan
update + clarification : Thanks for the answers guys ,localStorage is something i didnt know about. from what i understand about localStorage its only good for working in a single domain/location. (i encountered this question on site). what if i want the option of running the app from different locations - lets say there will be only one person updating the JSON data, no need for sync/lock and stuff like that. right now my files (JS,JSON..) are saved in dropbox ,this is how i can use the app from different locations today , i dont have any other server.
2'nd update : i tried the localStorage solution i've been offered and even though its a great capability ,its not exactly what i'm looking for since i need the JSON data available in more then one location (i'll be using my desktop and my laptop for instance).
i'd be glad if you have other suggestions.
Thanks Again.
Check out the HTML5 localStorage API. You will be able to store your JSON objects there and retrieve them. They will be stored as key-value pairs. You can't write to a file using JS AFAIK.
Don't use a file as storage, use localStorage: http://diveintohtml5.info/storage.html. If you need to save information on a session scope, you should use sessionStorage, mind though that the latter is not persistant.
An example of how you would use it:
var item = {
"general": {
"portfolioName": portfolioName,
"ownerFname": ownerFname,
"ownerLname": ownerLname
},
"riskManagement": {
"stocksPerc": stocksPerc
}
}
// set item, you should think up of a unique key for each item
localStorage.setItem('your-key', item);
// remove it if no longer needed, you don't have a lot of space
localStorage.removeItem('your-key');
Saving files is possible in some browsers but this will probably be removed in the future - so I wouldn't use it unless you must.
This article shows how to -
http://updates.html5rocks.com/2011/08/Saving-generated-files-on-the-client-side
You can post the json to a server and use the server to generate a download file (ask a new question if thats what you seek)
and finally - are you sure you want to save to file? if all you want is to save and restore data then there are better alternatives (such as localStorage, cookies, indexDb)