I'm working on Angular seed in my project.
I have two identical views(HTML pages) which are same (having same elements and functionality).
These two pages have GridView that are to be populated by same service as well but only the REST API URL is different for both of these pages. Now in my router.js, I want to use $stateprovider.state() to route to these pages.
My question is: Can I use a single controller for both these views or a separate controller for each. But, when I use the same controller for both view pages I get "Injector not defined" error.
Is there a different way to do it? What is the best procedure to handle such conditions?
This is a bit of a generic answer, I can update it if you provide some additional details or code. It's possible to use the same controller for different views. Although personally, I tend to try to avoid this, in case I later have to mod one of the views. I would use two different controllers, but put a lot of common code in a service/directives. I think it's a good practice to minimize the amount of business logic in your controllers.
If you have identical views, that only change an url, I would consider using an url parameter or route parameter for this. Then you would in reality only have one view and one controller.
Related
I've created a BookService that is used for storing (add), getting (getAll) and removing (remove) books. Now I want to use this BookService inside my controller to publish some methods that I can later use in my view. My controller looks like the following:
app.controller('BookController', ['BookService', '$scope', function(BookService, $scope) {
$scope.addBook = function() { BookService.add(); }
$scope.getAllBooks = function() { BookService.getAll(); }
$scope.removeBook = function() { BookService.remove(); }
}]);
As you can see, the controller is just a proxy that forwards the method calls to the service. Is this in general bad practice? And is there a better way to solve that using Angular.js? Calling the service directly from the view without a controller seems, to me like a bigger problem.
Best Practice
From what I can see this is perfectly good practice, I'm assuming that you're using $scope here to bind these services to a button or something similar. The Idea of using a factory or a service is to create some well organised reusable code that you can then instantiate in your controller exactly like you have done.
Controllers can get quite complex so moving basic functionality to your service is the best thing to do. In your case you have a relatively simple controller so you may not see the benefit of coding in this way. But I assure you that as your code base grows you will be required to code like this just to keep things readable.
Note
Just as an extra note I've added a data process that you might take with an example of a database request
database > API > service/factory > controller > view
This would be the correct path to take when requesting something from a database.
What you have shown is not bad practice; it is in fact recommended that you abstract resource management logic (like adding, removing and finding resources of the same type) into a separate service, for organization and maintainability and reusability purposes.
I do understand from your example how the controller seems to be just a proxy to the service though, and why you would think it's repetitive and possibly redundant. Let me expand on your example to see if I can explain the reasons for abstracting the logic. In doing so, let's consider only the adding operation, even though the logic would apply to others as well.
Reason 1: adding a book (or any resource for that matter) in a web app is usually more complicated than just a bookService.add() call. It requires having some sort of form to enter the details, a submit button to handle the actual request, possible massaging of the entered data, adding new fields like time stamps and author ids, and persisting to some data storage. The first two or three of those steps would be applicable to the screen or view from which you are adding, so it makes sense to put that in a controller (the view model), whereas the rest of the steps should go into the generic service.
Now say you have another screen where you see a friend's list of books and you can add it to your list by selecting a book. In that case, the controller logic for that view's controller will differ from the previous example, but the service steps will still be identical, and thus do not need to be duplicated since the service can be injected into both controllers.
That's a big win.
Example 2: let's say you've already split the code between controller and service as describe in example 1 above. Then you decide that your data storage needs have changed and now you want to update your logic to save to a different database system. Now instead of having to change all the controllers, you just change your services and the everything works.
This is also a really big win.
Yes you'ved done this correctly. Just keep in mind that as you scaled up your app in complexity, you'll want to have isolated scopes, (and) decomposition into component directives. Each directive will have its own controller and template fragment.
I'm new to Ember, come from an Angular background. Let's say I have an number of elements, each of which holds a different data.
#elem1 10
#elem2 20
#elem3 30
I want to bind each of these elements individually to Ember models/controllers that hold the data. So something like:
script(type="text/x-handlebars", data-template-name="elem1").
{{data}}
App.Elem1Controller = Ember.ObjectController.extend({
data: 10
});
This should be really easy... but I'm having a hard time navigating through all the different naming conventions and routing/terminology of Ember. How can I go about doing this?
The first thing to determine is which route and controller is associated with your view and then wire up the components accordingly.
Here is a simple example in a JSBin.
This one uses a separate controller and route for the three properties. And they are rendered into the application outlet when the link is clicked.
If you need to use multiple controllers then you can include them in the controller that is associated with your view by using the "needs" dependency injection.
Here is another one that just uses the application template and associated controllers etc.
It also shows how you can include controllers in other controllers which might be more what you are looking for. It also shows you how to reference them in the template.
I'm making a single page application using Require.js and Backbone.js. Its a fairly large web app with a lot of different "pages" aka views. Below is my router to give you an idea. There are several main pages with sub pages.
So for example there's a Settings section that has multiple different sub pages such as user settings, language settings, email settings etc.
How would I structure many routes and their views for simplicity?
Right now Im giving each sub page its own view but that means I have to import 20-30 views into the router so that all possible views are available for when that page is routed.
Another way I thought of was to have one view for each section and that in that view I should load different partials. That way I only have to load the 5-6 section views into the router... but then the view would have to understand routing.
Whats the right way to do this?
I create 'controller' objects that take care of view rendering and model fetches.
I prefer to keep the router clean at all times, which means that I will don't clutter it with callback functionality. Doing so would make the router a mess over time, while part of its purpose would be to get a quick overview of the available routes.
In Backbone, I found that it is useful to create your own conventions, just like a framework would do.
For example, for every view I create, I will create one controller object.
Every controller object has a method that is named 'makeView()', and which takes care of rendering the view, as well as memory management.
In my own theory, I created a method of 'cascading controllers', in the sense that one controller may also control other controllers, and controllers may use 'helper' objects to fulfil certain tasks.
For example, when you say that you may need to manage 20 views and subviews; we could imagine that some of the views are related to each other; that there will be a central controller that takes care of common tasks between related views, and specific controllers that take care of specific, individual view functionality.
A route in my router looks something like this:
auth: function(){
//--- Check the authStatus and render status independent views
var auth_ctr = new Auth_ctr();
auth_ctr.makeViews();
}
In the example given, you could imagine that you will create and render multiple views. So what I really do, is instantiate new controllers from within this controllers, that each individually will create and manage views, provide functionality that support the view, get the collection/model data.
It would be important to create a sort of independent 'View manager' that prevents memory leaks from occurring when you render new views each time.
This is just how I do it, but of course, I'm sure there are people who do this differently.
It is a theory I came up with; it has given me a clear structure, and it has worked well for me until now.
Lets assume that I have two routes in an Ember application. These are totally separate routes names 'first' and 'second'. They have separate data models and different actions and so forth.
Everything is fine up to now.
How - we recognise that these parts of the application:
Are often used by the user together in an alternating fashion (do something in first, then in second then two things in first etc)
They take up little screen real-estate.
In a standard server side application, we would assume that we can create a new dashboard controller/view and somehow real in the other two controllers to handle all the things and diplay the results. The crucial thing is - composition does not change the 'first' and 'second' controllers or views.
I want to do the same thing, only in Ember. I've created this JSBIN to illustrate the problem.
I am aware of two existing solutions:
Use the existing models only (solution in the linked jsbin above) - the problem with this approach is obvious - the view are not used.
Use the Component approach - I believe that this is not a good fit because these are not general, reusable components, and should be able to stand up on their own.
An ideal approach for me would be to use the {{view}} helper to somehow invoke the views but also pass in the controller data. (I've had a go at it in this jsbin but can't get seem to get it to work the the data from the controllers or properly setup a model for the route).
In my opinion you will need to use the {{render}} helper
App.CompositeRoute = Ember.Route.extend({
model: function(){
return {
first: this.modelFor('first'),
second: this.modelFor('second')
};
}
});
in your handlebars template for the composite
{{render "first" model.first}}
{{render "second" model.second}}
Good luck
How do you organize the view-model classes? Separate classes or one giant one (and how to modularize the giant one)? How to switch between 'pages' (with data loaded with ajax of course)? How to load templates for backbonejs after page load? Examples and tutorials would be appreciated as long as they are more advanced that he ones on their site.
Wow, lots of questions all rolled into one. I'll try to hit them here, but a disclaimer that I am writing an entire course for Pluralsight on Knockout ... so i can't go into the depth you need an a comment box :)
1) How do you organize model-view classes?
I think you mean view-model classes. I recommend creating a view model that contains all of the properties and methods that the page requires. Put the view model in an enclosure and keep all of that javascript in its own file. For example, if you have page customers.html for your structure, you could have customers.js for with your view model.
2) Separate classes or one giant one (and how to modularize the giant one)?
Each view model is in its own file. Generally 1 view model per js file (but you could certainly put interrelated ones int he same file). Also, generally 1 view model per view (but again, you can go beyond this in some cases).
For Models you can create them all in a single models file if you like, or put them in separate files. For smaller apps I like 1 models.js files since most models are pretty straight forward, small, and contain simple properties (albeit observables). But here, it really is a matter of choice.
3) How to switch between pages?
The mechanism is not specific to Knockout, so you can use links or even custom controls (menus, tabs, etc). Your call. Once you decide how to navigate to a different page, I assume you need to pass data between the 2 for context One way to do this is in the querystring with an ID, another way is local storage (for larger items you need to store in the client), or there are other options too. Again, it really depends on what you need to pass between the pages. A lot of times I design the pages to be self sufficient so I dont need to pass much between them. For what I need to pass, i try to send as little as I can and look up data based on keys (in ajax calls or local storage ... wherever the data lives).
I hope this helps a bit.
UPDATE: Here is the link I mentioned to my Knockout.js course on Pluralsight