I'm using Angular 5.
I have "fake back-end" (array of items).
My case:
I'm waiting for the following structure of object:
id: number,
title: string
But, Back-End sends me wrong structure:
id: number,
name: string.
I need to receive data from back-end, and if field name (in my case "name" is wrong, should be "title") is wrong, I should RENAME field and return valid object.
P.S. I have interface and class
Good practice on large apps where you don't have much control over the backend is to create a mapper for each response type you expect.
For example you make an http request to retrieve a list of cars from your backend.
When you retrieve the response, you pass the data to a specific mapping function.
class CarMapper {
// map API to APP
public serverModelToClientModel(apiModel: CarApiModel): CarAppModel {
const appModel = new CarAppModel(); // your Car constructor
// map each property
appModel.id = apiModel.id_server;
appModel.name = apiModel.title;
return appModel; // and return YOUR model
}
}
This way on the client side you always have the correct data model. And you adapt on any model change made on the backend.
You can check if an object has name key and then create another object with title
if (obj.hasOwnProperty("name")){
var newObj = {
id: obj.id,
title: obj.name
};
}
obj = newObj;
Related
I am developing a node js project in which the end-user can create and update outlets in mongoDb database. Now, let's say there are hundreds of fields in the outlet schema but the user may not update each and every field, i.e one may update 2 fields, other may update 3 fields. So, I want to create a function that can handle each type of request. I don't know this can be done or there is some other way, but i am new to this, can you suggest me something suitable for my project. Thanks in advance!
Sorry for the confusion earlier.
I am developing a project in nodejs for retail outlets. Each outlet has over 50 fields in the database while registering. Registration is fine. The POST request via API specifies all the data required.
But when I am planning to update any of those field. I am not sure what approach to handle. Sometimes only 1 field will be changed or next time a bunch of them with no order/sequence.
Example :
{"id":"ABCD", "name":"MNOPQR"}
{"id":"ABCD", "time":123, "name":"ZYX"}
So here in first query I need to only update the name while in next I need to update both name and time.
Is there any way I can manage the dynamic json parsing at server end and updating only those fields (int database) that are mentioned in the request.
You have several approaches you can use.
One is to accept an object with the changes:
function doTheChanges(changes) {
Object.keys(changes).forEach(name => {
const value = changes[name];
// Use `name` (the field name) and `value` (the value) to do the update
});
}
Called like this:
doTheChanges({foo: "bar", biz: "baz"});
...to change the foo field to "bar" and the biz field to "baz". (Names that have invalid identifier chars, etc., can be put in double quotse: {"I'm an interesting field name": "bar"}.)
Alternately you could accept an array of changes with name and value prperties:
function doTheChanges(changes) {
changes.forEach(({name, value}) => {
// Use `name` (the field name) and `value` (the value) to do the update
});
}
Called like this:
doTheChanges([
{
name: "foo",
value: "bar"
},
{
name: "biz",
value: "baz"
}
]);
You could also just accept a varying number of parameters, where each parameter is an object with name and value properties:
function doTheChanges(...changes) {
changes.forEach(({name, value}) => {
// Use `name` (the field name) and `value` (the value) to do the update
});
}
Called like this:
doTheChanges(
{
name: "foo",
value: "bar"
},
{
name: "biz",
value: "baz"
}
);
Note that that's very similar to the array option.
Or use the builder pattern, but it's probably overkill here.
Instead of put request you can use patch request so that only the values you change get affected in database .
I have an Angular + Breeze + WebApi(EF) setup which works very well when querying for data. The breezeProvider is set for camelCase on the client by default, and PascalCase on the server side.
bp.NamingConvention.camelCase.setAsDefault();
The trouble I'm having is when pushing new data over signalR to my app. The data arrives PascalCased from the .NET Stack (Breeze explicity says to not mess with the casing on the server). I then use the standard factory to create a new entity and try to initialize it with the passed values. Since the initialier hash is all PascalCased, most of the properties fail to initialize properly. Is there a way to tell Breeze that it should convert this data the same way that it does when querying? I have not yet been successful. Basically, I just want Breeze to treat this the same as it treats all of the data it receives.
function onSignalRData(call){
var callType = manager.metadataStore.getEntityType("Call");
// call json from server is like { Id: 1, Name: "Paul", IsActive: true }
// I think Breeze expects { id: 1, name: "Paul", isActive: true }
var newCall = callType.createEntity(call);
}
Any suggestions? I see Breeze mentions manually defined naming conventions, but again I'm not doing anything exotic here, just doing the same thing that Breeze does on queries but in a creation initializer.
This may not be the best solution, but it seems to work for me. I used the same method as formatting json data to be camelCased and reparsed the data with a reviver function to camelCase it. I'm surprised that there's not a pipeline block in breeze entityManager.createEntity(...) that can handle this.
function reviver(key, val) {
if (key)
this[key.charAt(0).toLowerCase() + key.slice(1)] = val;
else
return val;
}
var parsed = JSON.parse(myjson, reviver);
I made a Character class shared by the client and server in the same js file.
The server instanciates these characters and stocks them in a characterList object. I send it to the client with socket.emit( 'updated_characters', characterList ), but the client gets back an object of Object, instead of an object of Character, so I can't use my Character's methods on them.
How can I get around that ?
You can't send custom object types directly using socket.io. socket.io uses JSON as the transport format for objects and JSON does not have the ability to record or rebuild custom object types.
So, what you need to do is to create a serialized format for your objects (which will also likely be JSON) and then when you read the data on the other end, you will construct a custom object in your own code and then pass it this data in the constructor from which it will initialize itself.
The canonical ways to do this is to create a serialize method for your custom object that creates a new plain object that contains all the relevant info that needs to be sent over the wire and does not contain references to other objects (since that can't be serialized). Keep in mind that objects often have housekeeping information that does not necessarily need to be sent to the other end. Then, create an initialize method for your custom object that can take this serialized data and properly initialize your object that you can use on the other end.
Here's a simple example:
function MyObject(data) {
if (data) {
this.init(data);
} else {
this.count = 0;
this.greeting = "hello"
}
}
MyObject.prototype = {
init: function(data) {
this.greeting = data.greeting;
this.count = data.count;
},
getData: function() {
return {greeting: this.greeting, count: this.count};
},
talk: function() {
say(this.greeting);
}
};
Then, on the sending end of things, if you have an instance of your object in item, you would send the data with:
socket.emit('updated_characters', item.getData());
And, on the receiving side of things, you would have this:
socket.on('updated_characters', function(data) {
var item = new MyObject(data);
// do something with the item here
});
socket.emit( 'updated_characters', JSON.stringify(characterList) );
we have to do JSON.stringify in order for socket to identify as JSON and display it in front-end
Take the following example from Angular's docs:
var CreditCard = $resource('/user/:userId/card/:cardId',
{userId:123, cardId:'#id'}, {
charge: {method:'POST', params:{charge:true}}
});
// We can retrieve a collection from the server
var cards = CreditCard.query(function() {
// GET: /user/123/card
// server returns: [ {id:456, number:'1234', name:'Smith'} ];
What is the correct way to map the data structure, an onject with 3 properties in this example, that returns from the server, without the need to "guess" the structure. see the comment "// server returns.. " - I don't want to assume that, but to have a more structural way, like an expected interface or something alike.
How do you map data in angular than ?
Hi I'm new to Backbone and I was just playing around with it a little, here is my code:
var Users = Backbone.Collection.extend ({
url : 'http://backbonejs-beginner.herokuapp.com/users'
});
var users = new Users();
users.fetch({
success: function () {
console.log(users);
}
});
The fetch call succeeds and I am returned with an object that looks like:
[
{
"id": "hqel839m1071rbggsxf7",
"firstname": "Thomas",
"lastname": "Davis",
"age": 12
}
]
How can I print different parts of the result?
For example I want to print the "id" parameter of the first item. Can I iterate it like an array?
I tried to do console.log(users[0].id) but it doesn't work.
Thanks.
Not to forget about the arguments passed to success callback of collection.fetch which are (collection, response, options). Check documentation here. You can use the collection argument to select a particular model. Check below code :
var Users = Backbone.Collection.extend ({
url : 'http://backbonejs-beginner.herokuapp.com/users'
});
var users = new Users();
users.fetch({
success: function (collection, response, options) {
//Will log JSON objects of all User objects
console.log(collection.toJSON());
//You can get a Model using 'id'
var user = collection.get("hqesig1ea1br2k6horay");
// Will log User Model for id "hqesig1ea1br2k6horay"
console.log(user);
//You can then fetch Model attributes this way
console.log("ID: ", user.get('id'));
console.log("First name: ", user.get('firstname'));
console.log("Lastname : ", user.get('lastname'));
}
});
A fiddle for your reference.
There are three different ways to access the models in a Backbone.Collection. First, you can use the .get method to find a model based on it's unique ID. This basically looks at all models in the collection and compares their id attribute to the one provided.
var user = collection.get('unique_id'); // return an instance, or null
The second method is to use the .at method to get a model by index. This is useful if your models are sorted. If they are not sorted, they'll be fetched by insertion order (that is, the order in which they were provided to the collection):
var user = collection.at(0); // return the first model in the collection
Lastly, you can access the raw array of models that the Collection wraps. You can access this via the .models attribute, which is just an array. This is not the recommended approach.
var user = collection.models[0];
Once you have a user, you can access any attributes of the user via the .get method on your model:
var age = user.get("age");
user.set("age", 100);
You can view the documentation for the model get method here, and the documentation for Backbone.Collection here.