A form having fields for personal info And also states, Cities fetching data from api... How to Make them work all togather without submitting form - forms

Context
I have created a form which is taking user data like their name, phone no, address...
For the address I'm using an api that is fetching states to a drop-down and also the cities after selecting a particular state...
I've done the state part because it doesn't require a submit request.
Now, the problem is that...
For fetching cities I tried jQuery and ajax but that requires a post request and I have other details for the form too so how do I make the cities drop down fetch the data of selected state without submitting the form (POST REQUEST)?
Since nested form doesn't work in html it's difficult for me to find the solution..
Please help me on this..

You should make the fetch/ api call for the cities data on an event triggered by user over and the UI element which in your case should be the onChange event of the dropdown/select of the states.
const stateSelector = document.querySelector('.stateSelect');
stateSelector.addEventListener('change', function(e) {
getCitiesForState(e.target.value);
});
function getCitiesForState(state) {
fetch(`http://exapleapitogetallcitiesinstate/${state}`, {
"method": "GET",
})
.then(response => response.json())
.then(data => {
console.log("cities data", data)
// show cities dropdown, populate options in the select with the data
})
.catch(err => {
console.log(err)
});
}
Instead of vanilla js you can use jquery
for event handling
https://api.jquery.com/change/#example-0
and fetching data with
https://api.jquery.com/jquery.get/

Related

How to call multiple different apis using useEffect hook in React

I have a concern regarding calling the apis using axios in useEffect hook. For example, I have a react page where I am showing the all the list of consignments. A consignment can have a user from user list, a carrier from carrier list, an account from account list, a status from status list and a service from service list. All these lists are enumerated data. So, in this page where I have to get all the enumerated list before rendering the page, because in the react component, I have to display them as dropdown, so that users can apply filter on top of that. But getting the list of those enumerated data, I have to call the separate api. For example, getting users I have to call /users api and getting customers I have to call /customers api. My concern is do I need to call them using a single useEffect hook using the axios. Because I have to hit the server multiple times for getting those enumerated data. If the number of lists of enumerated data increases then my api request to the server will also increase. I don't know what is the best practice to deal with this kind of situation. Whether to create a single api so that the server is hit only once and all the enumerated data are returned or have the separate api and hit the server request to get separately to enumerated data. And hitting the server multiple times to get the enumerated data does it impact performance on the client-side I mean some memory leak? Just need some advice on that. Thanks in advance.
useEffect(() => {
const loadData = async () => {
try {
dispatch(getLoad(true));
const services = await Axios.get("/Services");
const customers = await Axios.get("/Accounts/Customers");
const resCarrier = await Axios.get("/Accounts/Carriers");
const resStatuses = await Axios.get("/Status");
setFilterData((prev) => ({
...prev,
services: services.data,
customers: customers.data,
carriers: resCarrier.data,
statuses: resStatuses.data,
}));
dispatch(getLoad(false));
} catch (error) {
dispatch(getLoad(false));
}
};
}, []);
You can use axios.all
axios.all([
axios.get(`/Services`),
axios.get(`/Accounts/Customers`),
axios.get(`/Accounts/Carriers`),
axios.get(`/Status`)
])
.then(axios.spread((services, customers, carriers, status) => {
setFilterData((prev) => ({
...prev,
services: services.data,
customers: customers.data,
carriers: carriers.data,
statuses: status.data,
}));
}));

self.addEventListener('fetch', function(e) { }) is not working

I have a doubt in PWA and will be glad if someone helps me with that. In my PWA I don't have any problem with storing static files like HTML, JS & CSS. But am facing Issues on dynamic data. i.e : my self.addEventListener('fetch', function(e) { }) is not getting called, but other functionalities are working fine i.e: 'install' and 'active' event.
to be more particular, I am using #angular/service-worker which worked fine but I created another sw file called sw.js. In my sw-js I'm listening to the events like 'install' 'active' and 'fetch'. My sw.js fetch is not getting called whereas the other two methods work well. But while fetching the ngsw-worker.js's fetch method alone gets called.
The thing I need is to make CRUD Operations in PWA with angular.
Thanks in advance!
You can do the dynamic caching like below , the service worker will intercept every request and add in to the cache.
self.addEventListener("fetch", function (event) {
event.respondWith(
caches.open("dynamiccache").then(function (cache) {
return fetch(event.request).then(function (res) {
cache.put(event.request, res.clone());
return res;
})
})
)
}
Note : You can't cache POST Requests
Can service workers cache POST requests?

Sails pubsub how to subscribe to a model instance?

I am struggling to receive pubsub events in my client. The client store (reflux) gets the data from a project using its id. As I understand it this automatically subscribes the Sails socket for realtime events (from version 0.10), but I don't see it happening.
Here's my client store getting data from sails
(this is ES6 syntax)
onLoadProject(id) {
var url = '/api/projects/' + id;
io.socket.get(url, (p, jwres) => {
console.log('loaded project', id);
this.project = p;
this.trigger(p);
});
io.socket.on("project", function(event){
console.log('realtime event', event);
});
},
Then I created a test "touch" action in my project controller, just to have the modifiedAt field updated.
touch: function(req, res){
var id = req.param('id');
Project.findOne(id)
.then(function(project) {
if (!project) throw new Error('No project with id ' + id);
return Project.update({id: id}, {touched: project.touched+1});
})
.then(function(){
// this should not be required right?
return Project.publishUpdate(id);
})
.done(function() {
sails.log('touched ok');
res.ok();
}, function(e) {
sails.log("touch failed", e.message, e.stack);
res.serverError(e.message);
});
}
This doesn't trigger any realtime event in my client code. I also added a manual Project.publishUpdate(), but this shouldn't be required right?
What am I missing?
-------- edit ----------
There was a complication a result of my model touched attribute, since I set it to 'number' instead of 'integer' and the ORM exception wasn't caught by the promise error handling without a catch() part. So the code above works, hurray! But the realtime events are received for every instance of Project.
So let me rephrase my question:
How can I subscribe the client socket to an instance instead of a model? I could check the id on the client side and retrieve the updated instance data but that seems inefficient since every client receives a notification about every project even though they only should care about a single one.
----- edit again ------
So nevermind. The reason I was getting updates from every instance is simply because at the start of my application I triggered a findAll to get a list of available projects. As a result my socket got subscribed for all of them. The workaround would be to either initiate that call via plain http instead of a socket, or use a separate controller action for retrieving the list (therefor bypassing the blueprint route). I picked the second option because in my case it's silly to fetch all project data prior to picking one.
So to answer my own question. The reason I was getting updates from every instance is simply because at the start of my application I triggered a findAll to get a list of available projects. As a result my socket got subscribed for all of them.
The workaround would be to either initiate that call via plain http instead of a socket, or use a separate controller action for retrieving the list (therefor bypassing the blueprint route). I picked the second option because in my case it's silly to fetch all resources data prior to selecting one.
Here's the function I used to list all resources, where I filter part of the data which is not relevant for browsing the list initially.
list: function(req, res) {
Project.find()
.then(function(projects) {
var keys = [
'id',
'name',
'createdAt',
'updatedAt',
'author',
'description',
];
return projects.map(function(project){
return _.pick(project, keys);
});
})
.catch(function (e){
res.serverError(e.message);
})
.done(function(list){
res.json(list);
}, function(e) {
res.serverError(e.message);
});
},
Note that when the user loads a resource (project in my case) and then switches to another resource, the client is will be subscribed to both resources. I believe it requires a request to an action where you unsubscribe the socket explicitly to prevent this. In my case this isn't such a problem, but I plan to solve that later.
I hope this is helpful to someone.

publishing user relevant data

I have created a simple, minimalistic diary app.
On the client, I use
Meteor.subscribe('entries', Meteor.userId());
to subscribe to the entries created by the user (stored in a mongodb collection). I pass the users ID to the publish function (on the server):
Meteor.publish('entries', function(userID) {
return Entries.find({userId: userID});
});
After login, Meteor.userId() isn't falsy anymore, because it's a reactive data source. However, the relevant data is not being published. I fixed that by auto-running the subscribe function:
Tracker.autorun(function() {
Meteor.subscribe('entries', Meteor.userId());
});
It works, but I feel it's a bad solution.
So here comes the question:
How should one publish user-relevant data in general? There must be a better way to do this, than passing the users ID to the publish-function. Also, isn't it insecure?
By the way, would love to hear some feedback on the app
You don't need to pass the userId from the subscription. Inside the publish function you can use this.userId to get the current user. You can also just return an empty array if the user is not logged in.
Meteor.publish("entries", function () {
if (!this.userId) return [];
return Entries.find({ userId: this.userId });
});

extjs form submit model design

I have a form template which contains around 30 kinds of forms. Each time only 1 form will be selected and submitted. The number of elements in the form varies but around 80 or even more.
I have 2 requirements for this:
The form submit should be able to cached into the localStorage and resumit to server later when network recover. How can i persistent the forms?
I don't want to put the model in the extjs because the model will be constructed at the true backend. And the backend will construct it based on the combination of user selections and inputs. Not sure this make sense or not. The only thing I can think of is to set the inputId by some rules and do the mapping at backend.
Any suggestion?
Could you push the base form data into a local object (array?), before submitting, and use $.ajax( ..., data:myDataObject ) to submit the data to the backend instead of the form? This way you'd have the data cached, can repopulate form, or resubmit as you need based on response.
I haven't used extjs (looks nice though), but I imagine something like this:
function submitter() {
var myData = new Object(); //maybe make an array/object to store each form dataset separately?
//pseudo:
for each form element {
myData.push(item = value);
}
$.ajax({
'dataType': 'json',
'type': 'GET',
'url': sSource,
'data': myData,
'success': [fnCallback, fnMy2ndCallback] //single or array of callbacks.
});
function fnCallback(response) {
//check for failure, or success and proceed accordingly.
}
Don
have a great day