I have been learning Angular and I made simple app which use database request and print all information from MySQL. In my service I made this method
getCharacters(){
return this.http.get('http://localhost/something/controller/characters')
.map(
(response: Response) => {
return response.json();
}
);
}
In characters-list component I used subscribe()
this.charactersService.getCharacters().subscribe(
(characters) => {
this.characters = characters;
}
);
It works of course but it's not practical. I want to use one array to a few components so I would retrieve data from MySQL one time and use this array in all components I want to.
How to do that?
Related
I'm relatively new to puppeteer and I'm trying to understand the patterns that can be used to build more complex apis with it. I am building a cli where I am running a WebGL app in puppeteer which i call various functions in, and with my current implementation i have to copy and paste a lot of setup code.
Usually, in every cli command i have to setup pupeteer, setup the app and get access to its api object, and then run an arbitrary command on that api, and get the data back in node.
It looks something like this.
const {page, browser} = await createBrowser() // Here i setup the browser and add some script tags.
let data;
page.exposeFunction('extractData', (data) => {
data = data;
})
await page.evaluate(async (input) => {
// Setup work
const requestEvent = new CustomEvent('requestAppApi', {
api: undefined;
})
window.dispatchEvent(requestEvent);
const api = requestEvent.detail.api;
// Then i call some arbitrary function, that will
always return some data that gets extracted by the exposed function.
const data = api.arbitraryFunction(input);
window.extractData(data)
}, input)
What i would like is to wrap all of the setup code in a function, so that i could call it and just specify what to do with the api object once i have it.
My initial idea was to have a function that will take a callback that has this api object as a parameter.
const { page, browser } = wait createBrowser();
page.exposeFunction(async (input) =>
setupApiObject(((api) =>
api.callSomeFunction(input)
), input)
However, this does not work. I understand that puppeteer requires any communication between the node context and the browser to be serialised as json, and obviously a function cant be. Whats tripping me up is that I'm not actually wanting to call these methods in the node context, just have a way to reuse them. The actual data transfer is already handled by page.exposeFunction.
How would a more experienced puppeteer dev accomplish this?
I'll answer my own question here, since i managed to figure out a way to do it. Basically, you can use page.evaluate to create a function on the window object that can later be reused.
So i did something like
await page.evaluate(() => {
window.useApiObject = function(callback: (api) => void){
// Perform setup code
callback()
}
})
Meaning that later on i could use that method in the browser context and avoid redoing the setup code.
page.evaluate(() => {
window.useApiObject((api) => {
api.someMethod()
})
})
onMounted(() => {
productService.value
.getProducts()
.then((data) => (products.value = data));
console.log((products))
});
When I print products with console.log, here what I have.
capture of the console
I see that the data I want are in RawValue but I don't know how to access them.
I tried Object.values(products) or just console.log(products._rawValue) or console.log(products.rawValue) it print undefined.
Do you know what function call ?
Thanks
There are 2 issues
#1 - you're using console.log(products) which shows you the reactive object, what you need instead is console.log(products.value) which will only show the value, which should match the content of data.produtcs
#2 - you might find that 👆 now shows an empty result. The reason that's happening is that you're calling the console log after the async function, but before it finishes, so you're calling it before it has a chance to update. To fix that, you can log as part of the async function
onMounted(() => {
productService.value
.getProducts()
.then((data) => {
products.value = data;
console.log(products.value);
})
});
If you're using the products inside a template, you don't need to worry about what's before or after the async function since it will re-render the component on change.
Also, you probably don't need to define productService as a ref, the class is likely not something that needs to be reactive, so you can just do simple assignment and then skip the .value to call getProducts
with axios what I do is take out the data with response.data you could try
onMounted(() => {
productService.value.getProducts().then((response) => (
products = response.data
));
console.log(products.length);
});
This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 2 years ago.
I am attempting to create a weather app using the Openweather API. I am able to retrieve the JSON object successfully, but I am having trouble iterating through the object, I would like to access the weather details for specific dates and times but I just cannot for the life of me wrap my head around the concept. There were times where I was able to access the name of the JSON object, but when I attempt to access a specific weather detail from a specific date and time, I am met with errors constantly. Some of the information is so deeply nested that I am unsure exactly how to retrieve the information
fetch(`https://api.openweathermap.org/data/2.5/forecast?zip=${zip}&units=imperial&appid=5672e526c1cbc8d71aed230e5e151426`)
.then(response => response.json())
.then(json => {
console.log(json.list);
});
}, [apiSearch]);
If I simply try to add an index to the end of json.list:
console.log(json.list[1]);
I am sometimes met with errors such as Cannot convert undefined or null to object or something along those lines, I would like to know the best way to access the object array below and all of its information, thank you!
I've tried multiple approaches including Object.keys, mapping, etc. but I always get hit with an object is null error or something of the sorts. I would like to iterate through the 40 arrays and lets say access the temperature, every attempt to do so has led me to failure. Any help would be greatly appreciated, thank you!
Hope this will help you.
fetch(`https://api.openweathermap.org/data/2.5/forecast?zip=99501&units=imperial&appid=5672e526c1cbc8d71aed230e5e151426`)
.then(response => response.json())
.then(json => {
const forcasetList = json.list;
forcasetList.forEach(f => {
console.log(f.main.temp)
})
});
There can be several issues here:
Fetch and response status
Since you are using fetch the returned response may not always be a valid response, you should first check that you have an HTTP 200 status response e.g.:
fetch(url).then(
response => {
if (response.status !== 200) {
throw new Error(`Expected status 200 ok got status: ${response.status}`)
}
return response.json()
}
).then(...)
Impartial / Invalid data
I am not familiar with the openweathermap API but from what i can see in the API the forecast list should always have complete non null objects.
But you could add some validation or guards by either e.g.:
Using a JSON schema validation like AVJ
Or having a parse method that checks for the list and returns non null elements
fetch(url).then(
response => {
if (response.status !== 200) {
throw new Error(`Expected status 200 ok got status: ${response.status}`)
}
return response.json()
}
).then(
forecast => {
// here you could validate using something like AVJ to
// check that the json response is valid
if (!valid(forecast)) {
throw new Error('Invalid forecast data')
}
// Some custom filtering and validation example
const list = forecast.list || []
return list.filter(
item => {
// filter out null objects
if (!item) {
return false
}
// other validations.
...
// validate the date is within your range
if (item.dt ...) {
return false
}
// valid item
return true
}
)
.map (
// extract the weather part
item => item.weather
)
}
).then(
weatherItems => {
// work with weather items here
}
)
Im trying to build an application that fetches data from an web API that returns XML. I want this data in JSON instead, but the API does not support that.
How do i fetch the data and convert it to JSON?
I tried to use xml2js and it seems to work, but i dont understand how to save it as an object so i can use it in my app.
async componentDidMount(){
const url = "this is where the APIurl are";
fetch(url)
.then(res => res.text())
.then(body => parseString(body, function (err, result) {
console.log(result);
})
);
}
result seems to return the data as json, but i cant figure out how to use the data as an object later.
Your best option is to use an external lib to do that. A quick search in google and I found this one https://www.npmjs.com/package/xml-js.
You should also check this question: Convert XML to JSON (and back) using Javascript
To store it on your app you should grab what you need from the parsed XML and put it on the state.
I'm learning Angular 6 and I have a List shown on my site. Now, i need to give Users of my site the possibility to add entries to that list. There's a form with 4 fields and a submit button, when Submit is clicked, the values should be stored anywhere and all the entries should be shown on the site, permanently, not just in the active session.
How can i achieve this? Do i need to include some sort of database? Or is it possible to append the new dataset to a JSON file?
Thank you in advance
EDIT: This is a training project and will only be available through the Intranet of the Company i work at, so security concerns about missing Captchas or similar things are not a factor
If you are going to use this project for long time and if number of entries is higher and you have alot of users, then you should use some data base. And if there is limited number of users and you need this app temporary then using json file is also good. Using json file will save you from database logics etc if you are not familiar with them
To SAVE some data anywhere you HAVE TO use some kind of database.
Angular is JavaScript framework. It helps to write applications. But it does nothing with server side (except, of course, CLI and other stuff which NodeJS people likes to do).
JSON is not the only way to communicate between browser and the server. But in Angular it's easiest way.
You'll need something on the server (I suppose PHP script) which will receives data from your Angular app and will send back some feedback. In the case with PHP you'd learn how to receive JSON POST ($_POST and $_REQUEST will not work)
What I advise you in terms "how to learn Angular" is go to this step-by-step tutorial https://angular.io/tutorial
Run it twice or three times and you'll understand how works Promises, Observables, communications, templates, services and all other stuff.
It is possible to append the data to the new dataset to the JSON file create a service to read that JSON file using that service so to give you the basics of reading that JSON file
Config.service.ts
#Injectable()
export class ConfigService {
private static _config: any = {}
constructor(private _http: Http) { }
load() {
return new Promise((resolve, reject) => {
this._http.get('../assets/' + 'data.json')
.map(res => res.json())
.subscribe((data) => {
console.log("inside http get of the new service");
console.log(data);
ConfigService._config = data;
resolve(true);
},
(error: any) => {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
});
});
}
// Gets a value of specified property in the configuration file
get(key: any) {
console.log("tell me the base :" + ConfigService._config['BASE_URL']);
return ConfigService._config[key];
}
}
export function ConfigFactory(config: ConfigService) {
return () => config.load();
}
export function init() {
return {
provide: APP_INITIALIZER,
useFactory: ConfigFactory,
deps: [ConfigService],
multi: true
}
}
const ConfigModule = {
init: init
}
export { ConfigModule };
add these lines in your main module
app.module.ts
import { CommonModule } from '#angular/common';
import { ConfigModule, ConfigService } from './config-service';
providers:[
ConfigService,
ConfigModule.init(),
]
Then, you can inject this service on any component or service that wants the data
Also, you have to add an assets folder under your app folder and place the data.json there.