problem with Display error messages in angular js - javascript

I need to display error message, when service issue.
i use below function to load data to the dropdown. function is loading in page load.
component
loadOrgNames(){
this.orgNameModel = this.dataserviceService.getOrgName();
}
service
getOrgName() : Observable<any> {
return this.http.get(this.orgnameurl);
}
how i handle errors in my service class.

the function getOrgName return an Observable, if the value is correct for dropdown use async pipe on your html. or use it like below:
this.dataserviceService.getOrgName().pipe(
tap(data => {
this.orgNameModel = data;
}))

This is how a service that returns Observable should be consumed.
Error should be handled like below:
loadOrgNames(){
this.dataserviceService.getOrgName().subscribe( response => {
this.orgNameModel = reponse;
},
errorResponse => {
});
}

Related

Request Body Missing in Spring while updating using PATCH API in react js

Spring shows - Resolved [org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public com.cg.bookstore.entities.OrderDetails com.cg.bookstore.controller.OrderDetailsController.updateDeliveryStatus(int,java.lang.String)]
Console shows - Uncaught (in promise) Error: Request failed with status code 400
class UpdateOrder extends Component {
state = {
deliveryStatus:""
}
handleChange = (event) => {
const deliveryStatus = { ...this.state.deliveryStatus };
this.setState({ deliveryStatus: event.target.value });
};
handleSubmit = (event) => {
// Prevents default behaviour of submit button
event.preventDefault();
console.log(this.state.deliveryStatus)
console.log()
OrderService.updateDeliveryStatus(this.props.match.params.orderDetailsId,this.state.deliveryStatus)
.then((res) => {
this.props.history.push("/admin/orders");
});
};
In OrderService I call the updateDeliveryStatus
async updateDeliveryStatus(orderId,deliveryStatus){
return await axios.patch(BASE_URL+"/"+orderId,deliveryStatus)
}
The updateDeliveryStatus service in spring
#Override
public OrderDetails updateDeliveryStatus(int orderId, String deliveryStatus)
{
Optional<OrderDetails> opt = orderDetailsRepo.findById(orderId);
OrderDetails od;
if (opt.isPresent())
{
od = opt.get();
od.setDeliveryStatus(deliveryStatus);
orderDetailsRepo.save(od);
} else
{
throw new OrderDetailsNotFoundException("Order is not found");
}
return od;
}
While I was testing backend in POSTMAN , I pass the input as plain string and it works fine. Is it because the input in not in form of json the issue? How to fix this ?
Usually, when using #PutMethod and wanting to update a resource you need to provide both ID of the resource you want to update and the new body, which in this case I presume is 'OrderDetails', error suggests is missing there.
Without java controller code it's only assumptions though.

SAPUI5 mock server doesn't receive requests

I didn't find a solution for this problem. I'm currently working with the CRUD Master-Detail Application WebIDE template and added some custom functions with OData calls. When running the app with mock server it loads the mock data. So far so good. But if I send a read request to the mock server it throws a 404 not found error.
Request URL
https://webidetesting[...].dispatcher.hana.ondemand.com/here/goes/your/serviceurl/MyEntity(12345)
Here's the mock server part in my index file flpSandboxMockServer.html:
<script>
sap.ui.getCore().attachInit(function() {
sap.ui.require([
"my/project/localService/mockserver"
], function (mockserver) {
// set up test service for local testing
mockserver.init();
// initialize the ushell sandbox component
sap.ushell.Container.createRenderer().placeAt("content");
});
});
</script>
The OData read call looks like:
onRemoveMyEntityBtnPress: function () {
let oEntityTable = this.byId("lineItemsList");
let aSelectedItems = oEntityTable.getSelectedItems();
let oModel = this.getModel();
for (let oSelectedItem of aSelectedItems) {
let sBindingPath = oSelectedItem.getBindingContext().getPath();
let sGuid = this._selectGuidFromPath(sBindingPath);
this._loadEntityFromService(sGuid, oModel).then((oData) => {
// Next step: change a property value
}).catch((oError) => {
jQuery.sap.log.error(oError);
});
}
if (oModel.hasPendingChanges()) {
oModel.submitChanges();
}
},
_loadEntityFromService: function (sGuid, oModel) {
return new Promise((resolve, reject) => {
oModel.read(`/MyEntity(${sGuid})`, {
success: (oData) => {
resolve(oData);
},
error: (oError) => { // call always ends up here with 404 error
reject(oError);
}
});
});
},
Does someone have an idea what I else have to do to send my read request to the mock service?
Finally found the solution!
I used the OData entity type to read my entity. I changed the destination to my entity set and now it doesn't throw a 404 error.

Implementing a custom ember-simple-auth Authenticator

Firstly, I am not a seasoned JS Developer, so please excuse obvious mistakes that I could have made.
I am trying to implement a custom Authenticator for authenticating a user with Keycloak using the OAuth2 Password Grant which requires the client_id be passed as part of the request body.
import OAuth2PasswordGrant from 'ember-simple-auth/authenticators/oauth2-password-grant';
export default OAuth2PasswordGrant.extend({
serverTokenEndpoint: 'http://localhost:8080/something/token',
makeRequest(url, data, headers = {}) {
data.client_id = 'my-app';
return this._super(url, data, headers);
}
});
I have a controller that uses this Authenticator by calling this action:
actions: {
authenticate() {
let {username, password} = this.getProperties('username', 'password');
this.get('session').authenticate('authenticator:oauth2', username, password).then(() => {
// Do something
}).catch((response) => {
// Show error
});
}
}
This causes Firefox to hang and gives me an unresponsive script message.
If I remove the return from the makeRequest() method, I can see from the browser debugger that the call to Keycloak actually returns correctly with the object that contains my token etc. However ember inspector shows some errors related to unresolved promises. But I guess that's because I'm no longer returning the promise.
What am I doing wrong here?
How can I fix the unresponsive script issue?
Is there another way for me to achieve my goal?
Edit 1: This is when I remove the return
Here is the actual object that is returned:
{
"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJTRUNSd09fMlZWdGhxUVBUWnFxNHlqX0tKekxnOElSTjBrQkx5UTlacklrIn0.eyJqdGkiOiI1NDgzZDdkMi0zMDdhLTQyZjItYWUxZC0xYTZjMTZjOTM2ZjAiLCJleHAiOjE1MDgzMzE5MjAsIm5iZiI6MCwiaWF0IjoxNTA4MzMxNjIwLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvc2Z4LWl0cmFuc2Zlci13ZWItYWdlbnQiLCJhdWQiOiJhZ2VudC13ZWItYXBwIiwic3ViIjoiMzZiMWY4OWMtNGYwMC00OTU1LWE0YzMtZWQ0NzZmZDU2OGM3IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiYWdlbnQtd2ViLWFwcCIsImF1dGhfdGltZSI6MCwic2Vzc2lvbl9zdGF0ZSI6IjQwODMxZWFhLTRmMmEtNDk2ZS05NDVkLTdiZWIxN2U0NmU0NCIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cDovL2xvY2FsaG9zdDo0MjAwIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJ1bWFfYXV0aG9yaXphdGlvbiIsImJhY2stb2ZmaWNlLWFnZW50Il19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwibmFtZSI6IlVtYXIgS2hvbHZhZGlhIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidW1hciIsImdpdmVuX25hbWUiOiJVbWFyIiwiZmFtaWx5X25hbWUiOiJLaG9sdmFkaWEiLCJlbWFpbCI6InVtYXJAYWlydmFudGFnZS5jby56YSJ9.eUJFklRiRjQPOC1rQLcqrljsSWmGXCpNNKqLJGAcvbnbwx8X0T1iqrmpFdyMN3EKRrIfTZyYRfcTEbpcBEjZcZtgDY9V0Ntvt4pvpUx_8Ey6I8xZQolHVwferjM30puLqG8MImADUimNrj3ghbJbAaCOJktIKgLnTIhDbkNb-8lzgbyq-rEP6lYAWjQ2OuOZnc8NQQ9CJiR9M1SB79SEmY2iQW9E_J8xo8BgZQ0GUBrhaWPo-Kn4RnlEcRNzVnlLHQKi5FM7Zpov3SMQUbAeLat38V41y09ap2XVCy7MfL_7-TrSlMx0TLrhWqPgA5aaXbmsT9_vKOoXNZoJ9bWCuA",
"expires_in":300,
"refresh_expires_in":1800,
"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJTRUNSd09fMlZWdGhxUVBUWnFxNHlqX0tKekxnOElSTjBrQkx5UTlacklrIn0.eyJqdGkiOiIxNTUwNDIyZS02OThkLTQ5N2ItODZmYi00YmY5MTFlMTcwYzYiLCJleHAiOjE1MDgzMzM0MjAsIm5iZiI6MCwiaWF0IjoxNTA4MzMxNjIwLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvc2Z4LWl0cmFuc2Zlci13ZWItYWdlbnQiLCJhdWQiOiJhZ2VudC13ZWItYXBwIiwic3ViIjoiMzZiMWY4OWMtNGYwMC00OTU1LWE0YzMtZWQ0NzZmZDU2OGM3IiwidHlwIjoiUmVmcmVzaCIsImF6cCI6ImFnZW50LXdlYi1hcHAiLCJhdXRoX3RpbWUiOjAsInNlc3Npb25fc3RhdGUiOiI0MDgzMWVhYS00ZjJhLTQ5NmUtOTQ1ZC03YmViMTdlNDZlNDQiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsidW1hX2F1dGhvcml6YXRpb24iLCJiYWNrLW9mZmljZS1hZ2VudCJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX19.XgYSZWwfaHeY1yZZuwnQ5bj-0IHP4UEmiPTqaeCE1KVyjl3kZz3HJVisndtcKPr05kalS-M_NqU0TaYvbcZ_zesJRIga5sz4gGRqObUmUCUJoQ_iWoOhbM2SutiVnlfgJDACvOxegIcSvakZTgQsEcSweio_0kMFqi-2DYzFp6Rl0TpQ8vALLkc7rEOonUGyt7S4qQzkT-xB1_ZDlSVfm6mC-QKYNZhtqBT18P7MKxBhEgwrJtCytA_4ft7qNAbgvZ3kUohcbhzxGvtHej5RKHNI2wTzwK3IWHbkLWNndxSk_Lzj2-lCx380VpTkVpiDJfq5umjskOmI13dyPF7paA",
"token_type":"bearer",
"not-before-policy":0,
"session_state":"40831eaa-4f2a-496e-945d-7beb17e46e44"
}
This is what ember inspector (Promises) shows:
Here is the stacktrace from the Promise:
Ember Inspector ($E): authenticate/<#http://localhost:4200/assets/vendor.js:77927:9
initializePromise#http://localhost:4200/assets/vendor.js:63591:7
Promise#http://localhost:4200/assets/vendor.js:64067:35
authenticate#http://localhost:4200/assets/vendor.js:77919:14
authenticate#http://localhost:4200/assets/vendor.js:78528:14
authenticate#http://localhost:4200/assets/vendor.js:79420:14
authenticate#http://localhost:4200/assets/sfx-itransfer-web-agent.js:855:9
join#http://localhost:4200/assets/vendor.js:20249:24
run$1.join#http://localhost:4200/assets/vendor.js:37657:12
makeClosureAction/</<#http://localhost:4200/assets/vendor.js:29073:16
exports.flaggedInstrument#http://localhost:4200/assets/vendor.js:37087:14
makeClosureAction/<#http://localhost:4200/assets/vendor.js:29072:15
submit/<#http://localhost:4200/assets/vendor.js:70453:20
tryCatch#http://localhost:4200/assets/vendor.js:63549:14
invokeCallback#http://localhost:4200/assets/vendor.js:63562:15
publish#http://localhost:4200/assets/vendor.js:63532:9
#http://localhost:4200/assets/vendor.js:54458:16
invoke#http://localhost:4200/assets/vendor.js:19948:17
flush#http://localhost:4200/assets/vendor.js:19827:25
flush#http://localhost:4200/assets/vendor.js:20019:25
end#http://localhost:4200/assets/vendor.js:20128:26
run#http://localhost:4200/assets/vendor.js:20212:21
join#http://localhost:4200/assets/vendor.js:20219:24
run$1.join#http://localhost:4200/assets/vendor.js:37657:12
handleEvent/<#http://localhost:4200/assets/vendor.js:58233:18
exports.flaggedInstrument#http://localhost:4200/assets/vendor.js:37087:14
handleEvent#http://localhost:4200/assets/vendor.js:58232:17
_Mixin$create.handleEvent#http://localhost:4200/assets/vendor.js:57385:12
_bubbleEvent#http://localhost:4200/assets/vendor.js:57685:14
setupHandler/<#http://localhost:4200/assets/vendor.js:57619:20
dispatch#http://localhost:4200/assets/vendor.js:5546:16
add/elemData.handle#http://localhost:4200/assets/vendor.js:5355:6
Actually you solution looks like right.
I guess you have a problem in server response or mismatch request methods GET/POST. To solve this try to debug promise inside makeRequest.
return new RSVP.Promise((resolve, reject) => {
fetch(url, options).then((response) => {
response.text().then((text) => { //<-- here debug text
let json = text ? JSON.parse(text) : {};
if (!response.ok) { //<-- and here debug response
response.responseJSON = json;
reject(response);
} else {
resolve(json);
}
});
}).catch(reject);
So if problem will here, just rewrite whole method of makeRequest and add you own promise with custom fetch.
Another way is to write custom Authenticator, overriding authenticate, restore and (optionally) invalidate methods as wrote in documentation: https://github.com/simplabs/ember-simple-auth#implementing-a-custom-authenticator

React - Loading Stored Data then API data in ComponentWillReceiveProps

I have a component that must make an HTTP request based off new props. Currently it's taking a while to actually update, so we've implemented a local store that we'd like to use to show data from past requests and then show the HTTP results once they actually arrive.
I'm running into issues with this strategy:
componentWillRecieveProps(nextProps){
this.setState({data:this.getDataFromLocalStore(nextProps.dataToGet)});
this.setState({data:this.makeHttpRequest(nextProps.dataToGet)});
//triggers single render, only after request gets back
}
What I think is happening is that react bundles all the setstates for each lifecycle method, so it's not triggering render until the request actually comes back.
My next strategy was this:
componentWillRecieveProps(nextProps){
this.setState({data:this.getDataFromLocalStore(nextProps.dataToGet)});
this.go=true;
}
componentDidUpdate(){
if(this.go){
this.setState({data:this.makeHttpRequest(this.props.dataToGet)});
}
this.go=false;
}
//triggers two renders, but only draws 2nd, after request gets back
This one SHOULD work, it's actually calling render with the localstore data immediately, and then calling it again when the request gets back with the request data, but the first render isnt actually drawing anything to the screen!
It looks like react waits to draw the real dom until after componentDidUpdate completes, which tbh, seems completely against the point to me.
Is there a much better strategy that I could be using to achieve this?
Thanks!
One strategy could be to load the data using fetch, and calling setState when the data has been loaded with the use of promises.
componentWillRecieveProps(nextProps){
this.loadData(nextProps)
}
loadData(nextProps){
// Create a request based on nextProps
fetch(request)
.then(response => response.json())
.then(json => this.setState({updatedValue: json.value})
}
I use the pattern bellow all the time (assuming your request function supports promises)
const defaultData = { /* whatever */ }
let YourComponent = React.createClass({
componentWillRecieveProps: function(nextProps) {
const that = this
const cachedData = this.getDataFromLocalStore(nextProps)
that.setState({
theData: { loading: true, data: cachedData }
})
request(nextProps)
.then(function(res) {
that.setState({
theData: { loaded: true, data: res }
})
})
.catch(function() {
that.setState({
theData: { laodingFailed: true }
})
})
},
getInitialState: function() {
return {
theData: { loading: true, data: defaultData }
};
},
render: function() {
const theData = this.state.theData
if(theData.loading) { return (<div>loading</div>) } // you can display the cached data here
if(theData.loadingFailed) { return (<div>error</div>) }
if(!theData.loaded) { throw new Error("Oups") }
return <div>{ theData.data }</div>
}
)}
More information about the lifecycle of components here
By the way, you may think of using a centralized redux state instead of the component state.
Also my guess is that your example is not working because of this line:
this.setState({data:this.makeHttpRequest(this.props.dataToGet)});
It is very likely that makeHttpRequest is asynchronous and returns undefined. In other words you are setting your data to undefined and never get the result of the request...
Edit: about firebase
It looks like you are using firebase. If you use it using the on functions, your makeHttpRequest must look like:
function(makeHttpRequest) {
return new Promise(function(resolve, reject) {
firebaseRef.on('value', function(data) {
resolve(data)
})
})
}
This other question might also help

Ember Understand execution flow between route/controller

I have a "box" route/controller as below;
export default Ember.Controller.extend({
initialized: false,
type: 'P',
status: 'done',
layouts: null,
toggleFltr: null,
gridVals: Ember.computed.alias('model.gridParas'),
gridParas: Ember.computed('myServerPars', function() {
this.set('gridVals.serverParas', this.get('myServerPars'));
this.filterCols();
if (!this.get('initialized')) {
this.toggleProperty('initialized');
} else {
Ember.run.scheduleOnce('afterRender', this, this.refreshBox);
}
return this.get('gridVals');
}),
filterCols: function()
{
this.set('gridVals.layout', this.get('layouts')[this.get('type')]);
},
myServerPars: function() {
// Code to set serverParas
return serverParas;
}.property('type', 'status', 'toggleFltr'),
refreshBox: function(){
// Code to trigger refresh grid
}
});
My route looks like;
export default Ember.Route.extend({
selectedRows: '',
selectedCount: 0,
rawResponse: {},
model: function() {
var compObj = {};
compObj.gridParas = this.get('gridParas');
return compObj;
},
activate: function() {
var self = this;
self.layouts = {};
var someData = {attr1:"I"};
var promise = this.doPost(someData, '/myService1', false); // Sync request (Is there some way I can make this work using "async")
promise.then(function(response) {
// Code to use response & set self.layouts
self.controllerFor(self.routeName).set('layouts', self.layouts);
});
},
gridParas: function() {
var self = this;
var returnObj = {};
returnObj.url = '/myService2';
returnObj.beforeLoadComplete = function(records) {
// Code to use response & set records
return records;
};
return returnObj;
}.property(),
actions: {
}
});
My template looks like
{{my-grid params=this.gridParas elementId='myGrid'}}
My doPost method looks like below;
doPost: function(postData, requestUrl, isAsync){
requestUrl = this.getURL(requestUrl);
isAsync = (isAsync == undefined) ? true : isAsync;
var promise = new Ember.RSVP.Promise(function(resolve, reject) {
return $.ajax({
// settings
}).success(resolve).error(reject);
});
return promise;
}
Given the above setup, I wanted to understand the flow/sequence of execution (i.e. for the different hooks).
I was trying to debug and it kept hopping from one class to another.
Also, 2 specific questions;
I was expecting the "activate" hook to be fired initially, but found out that is not the case. It first executes the "gridParas" hook
i.e. before the "activate" hook. Is it because of "gridParas"
specified in the template ?
When I do this.doPost() for /myService1, it has to be a "sync" request, else the flow of execution changes and I get an error.
Actually I want the code inside filterCols() controller i.e.
this.set('gridVals.layout', this.get('layouts')[this.get('type')]) to
be executed only after the response has been received from
/myService1. However, as of now, I have to use a "sync" request to do
that, otherwise with "async", the execution moves to filterCols() and
since I do not have the response yet, it throws an error.
Just to add, I am using Ember v 2.0
activate() on the route is triggered after the beforeModel, model and afterModel hooks... because those 3 hooks are considered the "validation phase" (which determines if the route will resolve at all). To be clear, this route hook has nothing to do with using gridParas in your template... it has everything to do with callling get('gridParas') within your model hook.
It is not clear to me where doPost() is connected to the rest of your code... however because it is returning a promise object you can tack on a then() which will allow you to essentially wait for the promise response and then use it in the rest of your code.
Simple Example:
this.doPost().then((theResponse) => {
this.doSomethingWith(theResponse);
});
If you can simplify your question to be more clear and concise, i may be able to provide more info
Generally at this level you should explain what you want to archive, and not just ask how it works, because I think you fight a lot against the framework!
But I take this out of your comment.
First, you don't need your doPost method! jQuerys $.ajax returns a thenable, that can be resolved to a Promise with Ember.RSVP.resolve!
Next: If you want to fetch data before actually rendering anything you should do this in the model hook!
I'm not sure if you want to fetch /service1, and then with the response you build a request to /service2, or if you can fetch both services independently and then show your data (your grid?) with the data of both services. So here are both ways:
If you can fetch both services independently do this in your routes model hook:
return Ember.RSVP.hash({
service1: Ember.RSVP.resolve($.ajax(/*your request to /service1 with all data and params, may use query-params!*/).then(data => {
return data; // extract the data you need, may transform the response, etc.
},
service2: Ember.RSVP.resolve($.ajax(/*your request to /service2 with all data and params, may use query-params!*/).then(data => {
return data; // extract the data you need, may transform the response, etc.
},
});
If you need the response of /service1 to fetch /service2 just do this in your model hook:
return Ember.RSVP.resolve($.ajax(/*/service1*/)).then(service1 => {
return Ember.RSVP.resolve($.ajax(/*/service2*/)).then(service2 => {
return {
service1,
service2
}; // this object will then be available as `model` on your controller
});
});
If this does not help you (and I really think this should fix your problems) please describe your Problem.

Categories

Resources