Backbone Newbie: Approaching layouts - javascript

I have a backbone app (linked to rails) that currently looks a lot like a standard RESTful resource.
I currently have a 'new_post' link on my index page called via the following:
Backbonedemo.Views.PostsIndex extends Backbone.View
# ...
events: ->
'click #new_post' : "newPost"
newPost: ->
Backbone.history.navigate("/posts/new", true)
# ...
I'd like to include that on each of the backbone RESTful pages I have (index, show, edit, etc) and I'm wondering how to do it.
My initial plan was to place the #new_post html in the (non-backbone) parent rails template, but I couldn't figure out where to bind an event from each backbone view.
Alternatively, I guess I could throw in some sort of layouts in the (eco) templating system.
Last - and least desirable - is to set up a click #new_post event in each view, and render it in each backbone template. Blergh.
So, what's the most elegant way of approaching this? Is there a place to elegantly place event bindings across multiple templates? Ie the router or something, and if so, how?
Many thanks

If on click the only action is to change the route of the page, you can simply make the #new_post a link to /post/new and skip making any programmatic changes.

Related

Stimulus.js way to load a partial?

We are investigating Stimulus.js for use with our Rails6 app and keep hitting conceptual walls in moving our thinking from jQuery to Stimulus.
For example:
On one part of the page we have a button and when that button is clicked we want to load content into a div on another part of the page. In jQuery this is simple - respond to click event, load in the part from the rails backend into that div.
In Stimulus, how to do this? It looks like everything needs to be in one big controller so that the button can see the 'target div'. So essentially we are writing 'page' controllers, which seems a lot of overhead. Also, it messes up the way we are breaking down the page into partials because now those partials need to share a Stimulus controller.
You definitely don't need to be writing 'page' controllers. The idea is that you write smaller controllers for interactive elements. If you post more about your use case perhaps we can help you split apart your controllers. You are correct though that the controller's element must contain any element registered as a target. Just remember you can access elements outside that context (e.g. in a completely different part of the page) using regular Javascript (in other words document.getElementById can give you access just as easily as using Stimulus targets)
To answer your question though, you can do something like this:
show() {
fetch("/path/to/partial")
.then((res) => res.text())
.then((html) => {
const fragment = document
.createRange()
.createContextualFragment(html);
this.element.appendChild(fragment);
// OR document.getElementById("testy_element").appendChild(fragment)
});
}
What this does is fetch an HTML response from the Rails server and insert it inside of the main controller's element (this.element). For example:
<div class="container" data-controller="test">
<button data-action="test#show">Do the Thing</button>
<!-- partial would appear here -->
</div>
What you are looking for is Stimulus’s sibling library Turbo, made to handle HTML navigation through turbo-frames and partially updating the page through turbo-streams.

Remove dynamic segment information from route emberjs

I have an ember engine, and within that I have defined a route. It works as expected. It's called my-route. It was defined like this:
this.route('my-route', {path: '/my-route/:myparams'}); in the routes.js file.
As you can see, it has a dynamic segment, and shows different values based on myparams.
I want to add a nested route to this route. Let's say .../my-route/1 shows a list of items. When the user clicks on any of the items listed on the page, the route should be: my-route/display but instead its my-route/1/display. I don't want the 1 here as it could be misleading.
Also, the link-to doesn't open anything either, the click does nothing.
This is how I changed my routes.jsfile:
this.route('my-route', {path: '/my-route/:myparams'}, function() {
this.route('display');
});
In display.hbs file I added dummy data, and display.js is also empty, just extending from Ember.route.
The my-route.hbs links like this:
{{#link-to 'my-route.display'}} Open me {{/link-to}}'
I am new to EmberJS, and would appreciate if someone could please tell me how to:
Remove the dynamic segment information
Make the link-to work
Thank you!
1) I can think of no easy way to remove dynamic segment from the url -- if you must, you can probably just not use dynamic segment and send the information to the transitioning route via other ways - you can probably set the controller directly
"newRoute.controller.set('someProperty', my_param);"
or use needs api (http://emberjs.com/guides/controllers/dependencies-between-controllers/)
but note that both these methods would be making use of controllers. If you need to load data in the route depending on the query params, what comes to mind is using a service
But these methods are not very sophisticated and I'd say only go for it if dynamic segment is an absolute no.
2) this one is easier -- you need to pass in the dynamic part along with the route name when using link to -- as given in ember guide
https://guides.emberjs.com/v2.0.0/templates/links/
Based on the discussions with #Lux and #Chhirag Kataria, I ended up making two separate routes. I used the my-route as a dummy route, and nested the display and the list routes in it.

Angular UI-router nested views capabilities

I am trying to learn and understand the capabilities of UI-router with Angular 1.3.15.
I am trying to set up an application which has many views that have a header and footer directive. It also has a smaller number of views that do not need this setup, with the loaded view taking up the entire page.
Therefore, it seems I should handle this divergence "one level down", as in my diagram below. In the past, I have worked on ui-router apps with the index.html coded with the header/footer directives and a single ui-view for the other pages to load into. This time I am trying to get it correct form the start. Opinions and advice welcome.
I'm not sure what you want to know.
Yeah, you should handle the difference in templates the way you suggested: the root template should contain only the elements which appear on all states. Elements which appear on some states should go on those states templates, in the template of a parent state (if it makes sense), or in directives that you reuse in the various templates.
Instead of directives, you might want to use named views if your templates have some peatures in common, but the differences between them are not inside a single DOM element. For example, maybe all your pages have a small toolbar on top that always has some buttons, but other buttons depend on the state you are in. You can place that constant part of the toolbar in the root template, together with a <div ui-view="toolbar"></div>. The states would then define a view named toolbar with a template with the buttons they want to add.
You could make a directive for that toolbar with all the global buttons in its template and use <ng-transclude> to add the custom buttons at each state's template, but using named views seems cleaner.

Backbone MVP - Who attaches the view?

So I am writing a Backbone.js application.
I have opted to use the MVP pattern with Passive Views.
Now my arch so far is:
Application
Page Presenter
Layout View
Header Presenter
Layout View
Logo View
User View
Content Presenter
Layout View
Footer Presenter
Layout View
Now I am very new to the concept of MVP (had a lot of experience with MVC).
So say I want to render the header's layout and then attach it to the Page Presenter's layout view, who's responsibility is it to do so?
Most often, I see simple HTML/Image elements contained in a view template that is brought in via Handlebars, Underscore templating, or the like to the view. This allows you to keep your javascript and html separated. Absent that, HTML would live directly in the view.
The examples in this article make a common pattern for templates in MVP pretty clear.
I prefer to go one step further in my apps, starting with a common template in index for things like logos, main page layout, etc....then drawing my views in an element of that common template assisted by specialized, smaller, templates-per-view that contain specific html content to make the view work. The downside is that some template-per-views can be empty files, but that is a very rare occurance. It's also quite clear to the rest of the team where an element is going to be if they need to edit it.

JavaScript layout management for MVC/Backbone.js application?

My web application, written in Backbone.js, has what I call a number of "Modes".
Each mode describes which models and views that are currently active. By changing the mode parameter in the hash (#) I switch between modes and instantiate necessary Backbone models & views.
It seems logical to also describe the preferred layout and inject the container html code on a mode level.
Let's say the mode "PopulationPyramidMode" has a model and 3 Backbone views. The "HeaderView" should take up 30 pixels vertically. The "SidebarView" should take up 200 pixels horizontally and the "CanvasView" should fill moist of the screen and scale on resize events.
To complicate things further, the CanvasView holds a visualization which must be re-rendered on resize, i.e. the x/y-scales must be re-calculated.
So, what is the best approach to this?
1) Where should the layout logic go?
- On a separate layoutManager - and in that case how?
- Should each view describe its preferred size etc?
2) How do I inject the necessary HTML/CSS for my layouts and switch between them?
<!-- Layout 1 -->
<div id="header"></div>
<div id="sidebar"></div>
<div id="canvas"></div>
<!-- Layout 2 -->
<div id="header"></div>
<div id="canvas"></div>
Thanks for any specific hints and also on JavaScript layouts in general!
Just thinking out loud here. It sounds like you could have one view which manages the layout, but is capable of morphing the layout as needed. The question is: what triggers the layout change?
You might have a controller which is equipped with the routes and actions for these different modes. This controller could either hold an instance to this layout view and call a parameterized refresh function. Alternatively, the controller could trigger an event with the mode change and the view could be set up to listen for it. Once received, the view would call its refresh function.
My opinion regarding building such applications would be to use the straightforward observer pattern.
Design your controller in a way that it simply dispatches particular events when the hashtag changes. Have an event map in the controller,that acts as a reference table between events to be dispatched and the urls, better still, you can follow a particular convention regarding the choice of hash parts eg. everytime user navigates to url mydomain.com/#part1/part2 the controller dispatches an event 'evt_part1_part2'. You can use a common dispatch point (which can be a dom element, or a javascript object particularly being used for this very purpose).
Now all your views can listen to this common dispatch point, and if the event matches the one that this view is looking for, you can create the respective environment accordingly through that view.
This approach definitely helps in compartmentalization of views, leading of more modular and maintainable code.

Categories

Resources