How to make a SPA testable outside of the browser? - javascript

I have a SPA that pulls configuration data down from a server and generates a form that a user can proceed to fill out.
I want to be able to make this SPA testable outside of the browser, which would imply that the views and their implementations are not being tested.
Currently, the structure of a form is like so:
form
page 1
firstName
lastName
page 2
email
There is a form model which holds the data of the form and its configuration, and then there is a controller and a view. The controller attaches data from the model directly into the view, and also manipulates the view based on events. The view also has logic for creating and controlling certain aspects, such as inline scrollers (iScroll).
As you can probably see, this makes it impossible to test the code without the browser because the code is so tightly coupled to the view.
I think the way to fix the problem would be to have a controller, a controller model, a view, and then a concrete class that joins them together while providing the form configuration to the controller. But this raises some issues, specifically, that I would then need a factory for creating a controller for the form, pages, and fields, and then something that creates the concrete binder between the view and the controller, and then something that joins them all together in the correct way.
I feel like there has to be a better way to do this.
Any guidance would be greatly appreciated.

I think what you need is AngularJS. There is a template you can clone with git. It has testable capability right out of the box. I don't think there is a need to reinvent the wheel since there is already a well known framework that has this.

Related

Are event handlers in the view or the controller in an MVC application?

I am currently enrolled in a course on JavaScript Design patterns and I wanted to clarify the proper place for event handlers.
I noticed my professor's code included click handlers for a client side application in the view section -- my code accomplishes the same outcome, but I included click handlers in the controller.
In an MVC application, should event handlers be in the View or the Controller?
I think MVC in the web can only really loosely be considered true MVC. In the case of ASP.Net MVC, your javascript events can only really be part of the view (although should be separated into js files).
If you want to separate the js events from the view entirely, you're going to have a hard time. You're better off making an educated decision on which events are really related only to the view, and which need to interact with the controller.
For example, clicking on a menu item to expand and display sub-items, is 'an event' but the controller doesn't need to know about it. But loading data based on some selection would need to post, or submit through ajax, data to the controller.
In an MVC application, event-handling should definitely be placed in the view. It's a common misbelief by programmers not really aquainted with software design patterns, that event handling belongs to the controller maybe because of its name (controller = sth. that controls sth. ...).
The reason is that of portability, reuse of code and modularity: imagine you want to run your application on differrent platforms: PC, web, mobile phone device. Each specific platform has its own GUI-frameworks, libraries etc., so if you place event handling stuff, which is 100% GUI-platform specific (e.g. javafx, swing, android, struts, gwt ...) in the view, you can reuse the controller and the model and only have to deal with a new custom view.
The controller can be seen as a mediator between the view and the model, a middleware which is responsible for proper interaction between model and view.
Generally view should not have any logic besides rendering. So if you handler needs to call the server ( or do something else not related to rendering ) than it should be either in a model or a controller ( depending on a framework ). If you handler needs to do some animation, that logic probably should stay in a view ( if animation only pertains to a view ).
Usually when some event is triggered on a view it calls some method on its model ( view model ) that update the state of the model. When model is done updating its state ( synced with a server ) it fires an event that its view listens. When view sees that its model got updated it re renders itself.
Controller ( or may be a router if it functions as a controller ) usually only instantiates views and models.
Actually all of that will probably depend on a framework that you choose. I use backbone.js.

Calling into or between controllers in AngularJS

I have some fairly complicated logic in a bootstrap dialog which I've moved into its own controller for isolation.
There are times I want to launch the dialog or call a function in the controller based on some logic that occurs elsewhere in the app - in another controller, or a service. I've achieved this by adding an id to the ng-controller element then looking up the element by that id, and calling things off the .scope() of that controller. Essentially this:
In html:
<div id="modalController" ng-controller="modalController">
And in another service or controller:
angular.element("#modalController").scope().somefunction()
This seems pretty weird that I can't just get a controller by name. Is there a way to do this?
Create a service and bind the model to data maintained in that service. Make a change to the model within the service and it's made everywhere.
You could also create a service that provides a pubsub interface to the changes you need to make.
Yet another way to do it would be to have a single model representing the state of your system and modify that. Attach the relevant parts of that model to the scopes of each widget as necessary and you have a communication device built in.
It sounds like you are making a change in one place that should cause a change in another place. If that's the case, I'd argue having a service that updates all parts of the model correctly is the best way to go. Always imagine what you'd do if you added another widget that hangs off this functionality.

Are Backbone models supposed to be view-model, domain-models or both?

Sorry if the question is vague but I am really having trouble finding information on this. I come from the Flex/ActionScript world where, for the most part, we have very simple Value Objects (VOs) to represent things like a User or an Address and we have Models that usually represented collections of those VOs along with business logic. There were some frameworks that would include a view model, MVVM. I know that there is no "right way" to do these things but I can't seem to point my finger on the basics.
Are all Backbone views supposed to have their own models? Given that I will likely not have a view called "User", would I also include domain models?
Would folders look something like this?
App
models
domain
User
Address
view
UserProfileModel
views
UserProfileView
collections
Users
Again, sorry if this doesn't make sense or is too general. I am just trying to get an idea of how far along the JS world has gotten in terms of MVC patterns. Thanks.
I don't think there is an only-one answer here. Every case will have an answer.
Are all Backbone views supposed to have their own models?
No.
There will be Views that will make reference to a Model, other ones will be making reference to a Collection. There will be also Views making reference to multiple Models, and others those will make reference to no-Model at all.
A View is an User Interface. It shows data to the User and listen to the events the User trigger on this data representation.
For example, if I have a Model called Friend and I want to create an interface to list a bunch of this Models I'll have:
FriendsView: which is a View that represents a Collection of Friends.
FriendView: which is a sub-View of FriendsView wich represent only one Friend. It can also listen to the click on the destroy button for this Friend.
But also I'll want to have a form to search from Friends in my server:
FriendSearchView: which not have reference to any Model or Collection. But is listening to the User filling an input field.
Would I also include domain models?
I don't know what do you mean with domain models but if you are asking about where to put the business logic Backbone is very agnostic about that. I recommend to put as much calculation as possible into the Models or Collections. Also you can use your own pure JS Util library.
Keep the Views clean. Only responding to User events and calling Model and Collection methods as needed. Also listening in changes in the Model or Collection from which it is showing the data.
How folders should look like?
Well, Backbone is again agnostic about this. There are a lot of literature about this.
My projects use to be small, less than 30 files. I put all of them in the same folder with a naming convection like this:
Friend
Friends
FriendView
FriednsView

Where should I use templating, and where should I generate view objects programmatically?

I am using Backbone.js for an applciation involving a lot of different views, some nesting other views, and these other views could further nest other views.
Also view presentation depends on certain attributes in the model, for instance, some content is only shown if the user has been authenticated, or another type of an if-check
Coming from the world of Adobe Flex, I am used to declaring my views almost completely using markup, even deeply nested, or composite ones. Flex makes component declaration in markup a piece of cake.
I was kinda hoping that I could achieve the same kind of separation between the pure view presentation and the view logic in Backbone, but so far I've been struggling with that.
The reason for this is that in no way can I manage to declare a composite view using templates only. Thus, I have to resort to using BB's render() method to instantiate subviews and append them to the parent. This is OK ... but if the views get really granular, declaring them using JS is an overkill, because I literally end up appending pure HTML strings, which is a complete mess. This means that it is much better to use templating for those ones, and then just render the template instead of doing all the stuff using JS.
Using both approaches simply breaks any consistency in the application, but I push myself to be OK with it, because I've read a lot of (even professionally written) Backbone code, and I 've seen other people struggling with the same thing.
If I cannot avoid this separation of rendering approaches, then at least I will have to put any certain boundaries of which views should be rendered with a template, and which not, or just partially. The question is what will those criteria be.
My methodology is to have all markup contained in templates.
My conception of Backbone Views is that they are actually Controllers. If you consider a Controller in a more traditional web app framework, their job is to receive events, marshal models, fetch and render templates, passing in models, and to return the resulting output.
In Backbone, the Views are the elements responsible for this task. But, instead of http being in input/output medium, the DOM is the input/output medium.
So, I consider Views to be controllers for a specific area of UI on the screen. They listen for events, marshal models, fetch and render templates, and modify the DOM as a result.
The decision of when to go to the trouble of generating a sub-view vs. perhaps rendering a template in a loop, is fairly loose for me.
If it has the possibility of being used in multiple views, I'll make a View out of it.
If it has any events or user interactions which affect itself, but not really anything in the "parent" object I'll make a view out of it.
If it has any real logic, I'll make a view out of it.
If its a related model, or collection, I'll make a view out of it.
But, in any of these cases, the view does not directly generate HTML - I'll always store the markup in a template.

Knockout JS - Why do all the examples only contain ViewModel/View but no Model

I am looking through alot of the Knockout JS documentation available, however it doesn't seem to follow the MVVM pattern as I would expect (when looking at Wikipedia's definition of MVVM).
In all the examples they seem to show source code for ViewModels and Views however there is never a model, now it seems like most of the functionality that the model should contain (saving/retrieving a representation of data) is put within the ViewModel. I thought that maybe the ViewModels were actually more akin to the Model, and the binding layer that you kinda get for free is the ViewModel, as that does all the bindings...
So I am just wondering if I am missing something here? As I have a question open at the moment about where my UI logic should go, i.e adding Watermarks, Inter-View chatter etc and I haven't really got a solid answer for it, so wanted to confirm that my understanding of the pattern usage within this framework is correct before continuing.
In Web development, the Views and ViewModel are at the client-side.
The Models are at the server side.
The models represent the real objects while the View Models only represent them in terms of the view in which they are displayed e.g. in Customer Model you have all the information related to the Customer but in a Customer View Model you might only have Customer Name (because that's all your showing on the view).
Most of the knockoutjs example don't explain the Model bit is because it is server-side dependent and could be written in Ruby/C#/Python etc. Knockout only deals with the View Model and View; It's server side agnostic.
The server side tech is required to develop the Model layer in MVVM. Knockoutjs is required to develop the VM-V layer.

Categories