can't retrieve data from async call - javascript

I am using ngx-translate service for translations in my angular app. I would like to create method that would accept path to string which needs to be returned. My method looks like this:
public translateString(parameter: string): string {
let message = "";
this.translate.get(parameter).subscribe((response) => {
message = response;
});
return message;
}
But it always returns empty string, I think the problem is the subscribe call so return message gets executed before message = response. Any solutions?

The data is not synchronously available. You'll need to return the observable, and then the caller can subscribe to do what they need to do once the message is available.
public translateString(parameter: string): Observable<String> {
return this.translate.get(parameter);
}
// and then used like this:
SomeService.translateString('hello world')
.subscribe(message => {
console.log(message);
})

use instant
It not require any observables.
this.message = this.translate.instant('Language')

You need to return your message inside subscribe.Like this:
public translateString(parameter: string): string {
let message = "";
this.translate.get(parameter).subscribe((response) => {
message = response;
return message;
});
}

Related

Sending Post with JSON.stringify(obj) in body doesn't result in a string on API recieving side

So I'm a bit stuck on this scenario.
I have a frontend sending the following request through Axios to my API:
const objectInBody = {
Id,
Input
};
const result: any = await axios.Post(`Order/Reservation`, JSON.stringify(objectInBody));
return result.data;
And I have a RESTful .NET Core API running that recieves these requests.
Relevant routing logic:
[HttpPost("[action]")]
public async Task<IActionResult> Reservation([FromBody] string jsonObj)
{
Reservation reservation = JsonConvert.DeserializeObject<Reservation>(jsonObj);
try
{
var result = await orderManager.Reserve(reservation);
return Ok(result);
}
catch (Exception e)
{
return BadRequest(e.Message);
}
}
The problem here is, my API blocks the request, because my API doesn't recognize the 'JSON.stringify(objectInBody)' as a string and will not run through the code.
When I pass other strings, the API accepts it without any problem and continues the logic. Which is weird to me because I thought the JSON.stringify results in a string type?
On console.log(JSON.stringify(objectInBody)); I get {Id:1, Input:1} without quotation marks.
But when I console.log(typeof(JSON.stringify(objectInBody))); it does say 'string' in my console.
I can also adjust the "expected" type in my API to JsonObject or something else, but this is a bad 'fix', since it seems to me Json.Stringify has to return a string and pass it without problems, like I said, not a JsonObject ofcourse.
The reason that your current code is not working, is because Axios don't send Content-Type: application/json automatically for string payloads. Hence, to make your current solution working, you'll have to do like this (please follow my recommendation at the end of this answer instead):
const result: any = await axios.post("Order/Reservation", JSON.stringify(objectInBody), {headers: {"Content-Type": "application/json"}});
Recommended solution
You should change your controller method like this:
[HttpPost("[action]")]
public async Task<IActionResult> Reservation([FromBody] Reservation reservation)
{
try
{
var result = await orderManager.Reserve(reservation);
return Ok(result);
}
catch (Exception e)
{
return BadRequest(e.Message);
}
}
Then change your Axios call like this:
const result: any = await axios.post(`Order/Reservation`, objectInBody);
Assuming that Reservation class is like this
public class Reservation
{
public string Id {get; set;}
public string Input {get; set;}
}
Try this code
objectInBody = {
Id:"id",
Input: "input"
};
const result: any = await axios.Post('/Order/Reservation',
{ jsonObj:JSON.stringify(objectInBody)});

Angular API Call doesn't get called

Here is my code. I'm trying to display a list when a property is selected from a combobox. I'm getting the list from backend, but I get this error whenever I click the display button. Even though, the method is a GET method. What could be the problem?
TS:
filter() {
this._stockService
.getWarehouseTransferReport()
.subscribe((response: any) => {
this.dataSource = new MatTableDataSource(response);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
this.dataSource.filterPredicate = (data, filter) =>
this.filterPredicate(data, filter);
});
}
filterPredicate(data: IWarehouseTransferItem, filter: string) {
let searchText = data.Reference;
if (data.Reference) {
searchText += (data.Reference as any).toLocaleLowerCase("tr");
}
if (data.DeliveryNote) {
searchText += (data.DeliveryNote as any).toLocaleLowerCase("tr");
}
if (data.StockIntegrationCode ) {
searchText += (data.StockIntegrationCode as any).toLocaleLowerCase("tr");
}
if (data.Product.ProductName) {
searchText += (data.Product.ProductName as any).toLocaleLowerCase("tr");
}
return searchText.indexOf(filter) >= 0;
}
Service TS:
getWarehouseTransferReport(): Observable<IWarehouseTransferItem[]> {
return this._http.get("Stock/GetWarehouseTransferReport");
}
Backend C#:
/// <summary>
/// TRANSFER REPORT
/// </summary>
/// <param name="producdId"></param>
/// <returns></returns>
[HttpGet]
public List<DtoWarehouseTransferItem> GetWarehouseTransferReport(int producdId)
{
return WarehouseSpProvider.GetWarehouseTransferReport(producdId);
}
}
It probably means that server know the method but the target source is not supported. Here is the reference Mozilla link.
So basically it is not Angular Http client problem to be precise.
Reference link which shows many details on 405 status code problem. Link
Your C# Backend code requires a parameter int productId but I think you are not passing any parameter that's why it is now being called.
May be you are passing wrong object or object mismatches the value.
may be datatype issue or parameter count issue and your API needs
proper object and value.

How to return data from cloud function to android and use it?

How can I get data from Cloud onCall() function to Android client and use it in a java code?
The client connects to function and function connects to firestore. But I can`t get data back from the function to client. I know that data has json format. But how to pass data to android, and how to use this data in android code (for example to setText in TextView).
java onClick() method:
onClick(){
String first = editTextTitle.getText().toString();
String second = editTextDescription.getText().toString();
//Here I try to setText received from function, but nothing happen.
tv_function.setText(function_3(first, second).toString());
}
java - call function:
private Task<String> function_3(String first, String second) {
mFunctions = FirebaseFunctions.getInstance();
Map<String, Object> data = new HashMap<>();
data.put("text", first);
data.put("push", second);
return mFunctions
.getHttpsCallable("sendMessageToAndroid")
.call(data)
.continueWith(new Continuation<HttpsCallableResult, String>()
{
#Override
public String then(#NonNull Task<HttpsCallableResult> task) throws
Exception {
String result = (String)task.getResult().getData();
return result;
}
});
}
javaScript function:
exports.sendMessageToAndroid = functions.https.onCall((data, context) => {
var batono = {
first: data.fara,
second: data.mina
}
return db.collection('abra-codabra').doc("mu-mu").set(batono)
.then(()=>{
var arba = {
aram:"aramando",
borem:"boremuno"
}
return arba;
});
});
How to get var "arba" to AndroidStudio and set it to TextView?
By doing
Map<String, Object> data = new HashMap<>();
data.put("text", first);
data.put("push", second);
return mFunctions
.getHttpsCallable("sendMessageToAndroid")
.call(data)
...
(as shown in the example from the documentation) you send to your Callable Cloud Function a map with a text element.
However, in your Cloud Function code you do:
var batono = {
first: data.fara,
second: data.mina
}
So, it means that you should send a map with the following elements: fara and mina, not a map with text (or you would have done something like var batono = {text: data.text}).
So, you should most probably do something like the following (not tested however):
Map<String, Object> data = new HashMap<>();
data.put("fara", .....);
data.put("mina", .....);
data.put("push", true);
return mFunctions
.getHttpsCallable("sendMessageToAndroid")
.call(data)
...

RxJS BehaviorSubject: return current value or get a new one based on condition

I have a subject that consumers are subscribed to:
private request$: Subject<Service> = new BehaviorSubject(null);
This is the function that my components call upon initialisation:
public service(id: number): Observable<Service> {
return this.request$
.pipe(
switchMap((request) => request && request.serviceId ? of(request) : this.requestById(id)));
}
and the service call:
private requestById(serviceId: number): Observable<Service> {
// http call
}
Different components call this function with different ids. I'd like to renew/update the subject if the incoming id parameter value doesn't match of the id value of the current subject.
Is that possible to do? I have seen an iif function, but I don't think it suits me fully.
Thanks
This is what you can do:
public service(id: number): Observable<Service> {
return this.request$
.pipe(
//this is needed to ensure to avoid second evalution after doing next once
//we got the new service value from the API
take(1),
switchMap((request) => {
if(request && request.serviceId === id) {
return of(request);
} else {
return this.requestById(id)
.pipe(
//i am assuming that response of this.requestById is an instance of 'Service';
//update the subject
tap(s => this.requests$.next(s))
);
}
})
);
}

how to present a pop-up message based on Observable property?

I have a pop-up message that I want to present when my observable is delivered, its a string observable.
this is my function that returns string observable:
public sendUpdate() {
this._mtService.sendCurrentUpdate(this.myList).subscribe(
res => this.messageToDisplay = res,
error => this.messageToDisplay = error
);
}
this is my function that I present the pop up with the relevant message:
public showMessageDialog(message) {
let config = new MdDialogConfig()
.title('Message:')
.textContent(message)
.ok('Got it');
this.dialog.open(MdDialogBasic, this.element, config);
}
now, I want to know where and how should I call this message to present messageToDisplay when the observable is ready.
I t would be even better if you can tell me how I can show some loader while the observable is waiting to receive the string and then when its there present it...
I tried to do this:
public sendUpdate() {
this._mtService.sendCurrentUpdate(this.myList).subscribe(
res => this.messageToDisplay = res,
error => this.messageToDisplay = error
);
this.showMessageDialog(this.messageToDisplay);
}
but what happens here is that the first time i click on update i see an empty pop-up and if I click on it again I see the pop-up with the message, its obvious that it happens because the string didnt came back yet, but how do I get over it?
thanks!
The functions you pass to subscribe() will be called later/asynchronously, hence you need to call showMessageDialog() later as well:
public sendUpdate() {
this.showLoader();
this._mtService.sendCurrentUpdate(this.myList).subscribe(
res => { this.stopLoader(); this.showMessageDialog(res); },
error => { this.stopLoader(); this.showMessageDialog(error); }
);
}

Categories