I recently load several versions of MEANJS (meanjs.org) to understand the file structure better and view the changes.
In 4.0, articles.client.controller.js to be specific they have:
and I'm able to make changes to new Articles there as I appended new fields to the mongoose Schema.
$scope.create = function () {
// Create new Article object
var article = new Articles({
title: this.title,
content: this.content
});
In 4.1, it comes like this.
// Create new Article object
var article = new Articles({
title: this.title,
content: this.content
});
Now with 4.2, I don't see that in articles.client.controller.js,
vm.article = article;
I have my modified Schema version. How to make changes to the creation of a new Articles object? This is a good question for upgrading app from 4.0, 4.1 to 4.2.
It’s changed slightly.
Trying to use the resources directly as was done in version 4 may cause problems where the page is ready but not the resource (Article).
To get around this problem angular uses resolves which which use promises to handle the timing issues.
The important thing to know is that the promise will give you some answer at some point in the future - Just, it may not be the answer you'd like!
Either way, it always tells you once it has the answer - or more correctly once it has resolved.
Angular uses the promises to help out with the timing issues mentioned above. The resolves are keyed to a promise and will only load the controller once the resolve(s)... erm... resolve!
This means we will always have articles when we expect.
Promises, resolves - Let me at'em - Let me at'em!!
The resolves option is used in the updated articles.client.routes. Here we see that articleResolve is keyed to getArticle which isn't a promise itself but is instead a function which returns one (which is just a good!)
If we look at the lines below we can see how we create this promise returning function. It's a function which uses Angular's $stateParams (to inspect the state) and fill in the articleId for the requested article. We get the articles using the injected and familiar Articles service.
In your case you want to know how new articles are created so we must travel a little further into the articles service which has recently been updated.
This is almost the same as the Articles service which you are used to using, however the additional lines add an extra method to this service which allow it to create, or if existing to save the article details.
These lines are how we extend a service in angular and the below implementation basically checks the article to see wether it has the ._id property. This is the string representation of the .id property that all saved mongo db documents get.
It uses this information call the appropriate method.
Finally, back where we began
In the controller we see the earlier created promise key articleResolve used as the second injected argument; As if to say "when you have this articles service resolved use it as this second parameter when I'm injecting the arguments".
When we look at the controller definition, we notice that the corresponding second parameter is named article.
Background: Within any controller this actually points to the scope (or $scope). As convention†, and to make things in angular look like standard JavaScript where we often say var that = this, we create a variable to reference our scope.
Within the controller we attach this article to the scope so that it is accessible in the views via vm.article.
Fin!
† Graze at Papa John's style guide when you get chances and slowly evolve your code style to match it. It will help you avoid traps and as a side effect makes lot of the angular code examples/tutorial more understandable, especially where the authors also follow it.
Related
This is just a general question but I can provide an example if necessary. I've been working on a MongoDB/Mongoose, Node.JS, Express, and Handlebars stack app recently and I've ran into some issues with what is being passed from my route to the client side when dealing with Mongoose .find() queries.
I prefer to async await my queries. I have a deeply nested populate query that brings in all the data I need into one object. This is a very simplified breakdown of what I do
async function() { const finalObject = await Model.find({}).populate([*alot more populates*]) }
I pass this into my res.render() route, as so:
res.render('index', { finalObject });
The majority of my experience has been pretty straight forward. I have one issue in a separate stack overflow question about populating the same model twice in one chain (at different levels). I won't address that here.
I decided to do some calculations before passing the object to the route and attach some new values to the properties of the documents. This is where things get weird. I do some calculations and add new properties to documents (these properties are not part of the Schema). When the object is passed to the client-side, those properties I added are available to use (no problem here).
I needed to decode the finalObject into JSON and pass it as JSON as well for an easy use of the data in my client side JavaScript encodedFinalObject = encodeURIComponent(JSON.stringify(finalObject));
I decode it on the client side: clientSideFinalObject = JSON.parse(decodeURIComponent(encodedFinalObject)); and the properties I added are not there!
I'm wondering, how could the new properties I added pass through when I send the object but not pass through when I send the JSON? The decoding is the last thing I do before rendering the page, so it's not a matter of not having my code in the wrong order. I add the properties to the object then decode it.
Some research led me to find out that Model.find({}) does not return a native JavaScript object, but instead a Query. I'm assuming this is a user-defined class data-type that has special behaviors. My assumption is that between the passing from the back-end to the front-end, there is some middle step where the Query does its final processing.
The opposite situation has also occurred. As a solution to this, I decoded the Query finalObject immediately after the Model.find({}) and re-encoded it into a native JavaScript object. After that, I did all my calculations, attached the results as properties to the documents, and sent that new version over as the main finalObject (I still also sent over a separate decoded object for client-side JavaScript use).
This solved the issue of the new properties not being there. They appeared, but this time the decoded then re-encoded finalObject did not have the virtual properties of my Models. The main model has a virtual property that calculates some of it's other properties. It's almost as if that part of the query didn't execute within the .find({}) process. So, when I decoded the finalObject, the virtual properties were never there and were never decoded.
Can anyone explain to me what is going on? Thank you!
I am fairly new to ember. I have an existing Ember App and i need to implement a functionality in it. I have a Ember Object as below
`import Ember from 'ember'`
CallService = Ember.Object.extend
... other code here
_updateConnectedLeadId: (->
console.log "Do i get here??"
**pass the route action here**
).observes('some_other_here')
`export default CallService`
Unfortunately, i couldn't put the whole code here.
My route looks like
ApplicationRoute = Ember.Route.extend
actions:
showLead: ->
console.log data
console.log "did i get here?"
#transitionTo('dashboard')
`export default ApplicationRoute`
I tried using #send('showLead'), #sendAction('showLead') in my method but no luck.
My main intention is to make a transition once the console.log "Do i get here??" is displayed. I am not sure if i am on the right way here.
I also tried using #transitionTo('dashboard') and #transitionToRote('dashboard') directly but it throws me errors.
I have been stuck for a day on this now and i am clueless.
I'll be grateful for any guidance and help. Thanks
You have the problem that you are trying to trigger a route action or trigger a transition from within an Ember.Object, named call service. The code you create is unclear about where your custom object is being created; where the observer is triggered due to a change to object's property update, and so on.
Nevertheless, I tried to provide a working example for you. If you open the twiddle, you will see that I created a my-object instance within index.js route and pass it as model to my-component. When you click the button within my-component.hbs. The my-object instances dummyVariable is toggled and the observer within my-object executes. The tricky part here is that I passed index route itself as ownerRoute property to my-object instance; so that I can trigger the index route's dummyAction from within my-object.js with
ownerRoute.send('dummyAction');
so that related action executes and transition to my-route is performed. Although, I believe this might solve your question; I am not quite happy about the design. I do not think, it is a good way for Ember.Objects to know about routes, actions, controllers, etc. I believe the proper way is observing object's relevant properties from within this constructs and perform necessary actions by their own. Moreover, you might consider creating a service instead of an object and inject the service directly to your route instead of creating an instance of your class extending Ember.Object. If you have to extend from Ember.Object you can just inject relevant route, controller, etc to the instances of that particular object class by using an instance-initializer if you need.
Anyway, please take a look at the twiddle and ask more if you need to. I will be happy to help if I can.
I use Xamarin Forms with azure-mobile-apps-net-client with the .net backend. What I noticed is, that if I change a value in my mobile app for my model like
var dog = get_dog_from_sqlite_database();
dog.Color = "black";
and call
await dogTable.UpdateAsync(dog);
and then sync with the server, the Delta<Dog> patch object in the
public Task<Dog> PatchDog(string id, Delta<Dog> patch)
method in the backend, contains every property from my dog model, although changing just one value.
Is it possible to change some settings, that just changed values are patched to the backend? I ask, as I have to do some restrictions on who can change what values, so my backend code would be cleaner as I just have to look if a forbidden property was changed and then throw an exception.
No - when we do offline sync, we don't necessarily know which fields have changed - we don't keep that granular information. We just keep the new record. You can check out the operations queue in the SQLite database to confirm this.
I've been using Loopback to create an API. The documentation is generally really good but doesn't really answer my question about the following: how do I extend (not replace) a built in model?
The most promising piece of information came from this page - it specifies the way of basing a class from another class, via inheritance. This is useful but not ideal - I'd like to create relationships to custom models from the stock models, for example - "Role" should have many "Permission".
The page I mention also shows a Javascript file, located at common/models/<modelName>.js, where it states you can "extend" a model based on the properties and options you give it. The server never seems to hit the file... For example - I put a file in common/models/role.js with the following content:
var properties = {
exampleProperty: {type: String, required: true}
};
var user = loopback.Model.extend('Role', properties);
console.log('test');
First off, it doesn't seem to hit the file at all (no console.log output given). Second, obviously because of the first point, it doesn't extend the model with the properties I created.
Am I missing something obvious or is the documentation just plain wrong?
You should generate a new model via slc loopback:model named user. By default, the built in user is named User, which is why you can use lowercase user or even UserModel if you prefer. Then when you are prompted by the model generator for a base model, choose User. See https://github.com/strongloop/loopback-faq-user-management/blob/master/common/models/user.json#L3
I am currently playing around with node.js and MongoDB using the node-mongo-native driver.
I tested a bit around using the Mongo console storing and retrieving JS objects. I figured out, that if I store an object that contains functions/methods the methods and functions will also be stored in the collection. This is interesting since I thought that functions could not be stored in MongoDB (with the exception of the system.js collection, as suggested by the Mongo docs).
Also it will not only store the methods but actually each method and member of the object's entire prototype chain. Besides that I dont like this behaviour and think it's unintuitive I mustn't have it.
I was going to manage users in a Mongo collection. To do this I have a User object containing all of the users methods functioning as a prototype for each instance of an user. The user object itself would only contain the users attributes.
If I store a user in the Mongo collection I only want to store the own properties of the user object. No prototype members and especially no prototype methods. Currently I do not see how to cleanly do this. The options that I figured might work are:
creating a shallow copy using foreach and hasOwnProperty and storing this copy in the collection.
Add a data attribute to each user that contains all the object's attributes and can be stored in the collection.
This just came to my mind writing this: I could also set all the prototypes properties to not enumerable which should prevent them from being stored in the collection.
However, I do have the same issues the other way around: when loading a user from a collection. AFAIK there is no way to change an objects prototype in JavaScript after it was created. And there's also no way to specify a prototype to use when Mongo instantiates objects it retrieved from a collection. So basically I always get objects that inherit from Object using Mongo. As far as I can tell I have 2 options to restore a usable user object from this point on:
Create a fresh object inheriting from User and copying each attribute on the result object to the newly created object. (Compatible to storing mechanisms 1 & 3)
Create a fresh object inheriting from User and storing the result object as a data attribute on the newly created object. (Compatible to storing mechanism 2)
Are my assumptions, especially about the possibility to specify a prototype for query results, correct? What's the right way to do it, and why? I'm surely not the first person struggling to store and resurrect objects in/from MongoDB using node.js.
Currently I would go with the approach 2/2. I don't really like it, but it is the most efficient and the only one that works cleanly with the API. However, I'd much rather hear that actually the API does nothing wrong, but I do for not knowing how to use it correctly. So please, enlighten me :)
I just recently realized, that it actually is possible to change an objects prototype in V8/node. While this is not in the standard it is possible in various browsers and especially in V8/node!
function User(username, email) {
this.username = username;
this.email = email;
}
User.prototype.sendMail = function (subject, text) {
mailer.send(this.email, subject, text);
};
var o = {username: 'LoadeFromMongoDB', email: 'nomail#nomail.no'};
o.__proto__ = User.prototype;
o.sendMail('Hello, MongoDB User!', 'You where loaded from MongoDB, but inherit from User nevertheless! Congratulations!');
This is used all over various modules and plugins - even core modules make use of this technique, allthough it is not ECMAScript standard. So I guess it is safe to use within node.js.
I'm not sure I'm following you question exactly... but fwiw one thing came to mind: Have you checked out the Mongoose ORM? (http://mongoosejs.com/)
It gives you a lot of options when it comes to defining models and methods. In particular "Virtuals" might be of interest (http://mongoosejs.com/docs/virtuals.html).
Anyway, hope it helps some!