Handling events for multiple instances of Twitter Flight components - javascript

I'm aiming for a decoupled UI architecture. I want the carousel and pagination components to be separate from each other; but with the pagination able to listen for changes on a uiCarouselMoved event.
Example: http://jsbin.com/uQadehI/1/edit?html,js,output
The problem arises when I have two instances of carousels and pagination respectively. I'd like to be aware of the best design pattern within Twitter Flight to handle a 'bridge' between the Carousel and the Pagination components, without relying on irrelevant logic such as DOM tree structure, and preferably no hard-coded IDs.
So, is it possible to know which pagination to updated, based on the source carousel?

Creating a pagination mixin and mixing it in to the carousel would seem to make sense.
Another option is to use the DOM to provide structure. By attaching an instance of pagination and carousel to the same DOM node or tree, you create a non-declarative relationship between the two.
Alternatively, generate a unique ID (using, for example, _.uniqueId http://underscorejs.org/#uniqueId) and pass that with the data from the carousel. This can also be included in the response, allowing components to determine if they are interested in global events.
TweetDeck uses all three of these methods in various instances. Using the DOM for structure requires no extra boilerplate, though it is also the most implicit relationship. Using IDs is very specific but requires extra boilerplate in event triggers and handlers. Using a mixin requires no boilerplate and is very specific but does create a dependency, which you may want to avoid.

I would make pagination and carousel both mixins, with_carousel and with_pagination respectively, instead of individual components. This will allow you to use both within the same component, and attach that component to a new outer level dom node. This will allow you to listen for the uiCarouselMoved event locally instead of attaching the listener to the document.
An example is here:
http://jsbin.com/iZeLABAW/1/edit

Related

Should I use raw js or jquery to target DOM elements in a Vuejs 3 app?

 I'm creating an app using Nodejs and Vuejs 3. In this app I have made a sidebar that gets all links from a routes file and present them. This sidebar consists in a component that parents a list of other recursive link components.
 Since the links are recursive and many, I find it hard to deal with class toggling (active, showing, collapsed, etc.) on each of them and relate them to one another (if one is active the others shouldn't be) using only Vue. Should I use querySelector or any frameworks such as JQuery to handle them or should I try to stick with a pure Vuejs approach?
Edit:
 I don't want to gather the community's opinion on it. My aim is to understand pragmatically why I should or shouldn't manipulate the DOM "outside" of Vue.
If you're using Vue then let it be in control of the DOM; mucking around directly will only create conflicts and woe.
(The same applies to other SPA frameworks such as React and Angular.)
The main reason not to touch the DOM is that Vue works by modifying the DOM on its own, and expects to have complete control over it: when rendering components the framework is removing old DOM elements, adding new ones, updating event bindings, etc; and a lot of it is optimized to only update the DOM nodes that need to be updated.
If you go in there and start making direct changes that Vue doesn't know about, then it's likely that your own changes will get overwritten by Vue the next time it needs to render, or that your changes will overwrite bindings that Vue is depending on.
If you're very knowledgeable about Vue's lifecycle and know how to control when it does and does not render, it is possible to work with both together -- but even then it's still not a great idea. Vue and jQuery do very similar things, but in utterly different ways. In jQuery you build up the page and then use DOM traversals and event handlers to modify it; everything lives inside the DOM. In Vue you build up a bunch of components that manage their own state and rendering; the DOM is basically a side effect of the application state.
By trying to use both together you lose most of the advantages of each of them in isolation, and introduce a lot of complexity in having to manage two competing theories of state and render management (not to mention dealing with communicating data between them). Every time I've contemplated embedding a jQuery widget inside a Vue app, it's turned out to be much easier to just rewrite the widget in Vue directly.
This does mean changing a lot of habits about working with the DOM that you may have built up from past jQuery work. It sounds like you're trying to draw the whole DOM and then build your control structure into it afterwards, which is a natural way to think if you're used to jQuery; in Vue you'll want to build all of that logic into components so the framework can do the work for you. I'd suggest making one Vue component for a link that manages its own state for open / closed / active etc, that recurses to its children only when "open". Then just call that once with the top of your nav data instead of trying to manage the whole tree directly after the fact as you would in jQuery.

Best approach to component/visual inheritance in Angular 2?

I am new to Angular in general and starting in earnest with Angular 2, so I want to find out if I'm not thinking about this in the right way yet.
A "panel" is a page of content in my application. I'd like to use a base panel component to provide common UI and functionality to specific panel implementations that derive from it.
I'd like for the base panel component to have templated content that wraps the template provided by the derived component- this would, for instance, provide a standardized header whose content is provided by the derived implementation and allow for the child component to supply the page content itself.
The ultimate goal is to make it as easy as possible for developers to create new panels without having to worry about rendering the common parts, so that consistency can be enforced.
Also, I want for the developer to be able have two-way binding between base variables/properties that are programmatically set from the derived component and the corresponding elements that are rendered by the parent template... (in addition to the elements in their own child template).
Is this doable? Or am I thinking about this in the wrong way... not sure if I'm in an Angular state-of-mind yet.
As I've been working on this, I'm starting to think I may need to adjust to creating reusable components (like PanelHeaderComponent) that the developer would compose within their panel implementation rather than inheriting from a base for common UI... However, I do need for the container for all panels to be centrally managed somehow.
Want to be sure I do this the right way. Thanks!
I believe a valid approach is, like you said in your last paragraphs, to componentize your application.
Basically: Create reusable components for the different parts of your application (ie: Panel Header with Buttons with a certain style)
If you want different panels that will use the same header, you can then reuse that Panel Header in all of your your panels.
It would be analogous regarding buttons, and any other control that you want to use. Define your component, then reuse it everywhere, then reuse the reusable, composite components that you defined.
Important Note: As of now, and as far as I'm aware, there's no Visual Inheritance between components, so in order to simplify your job, you might want to use sass to define the styles and take advantage of #imports in order to DRY.

How to create a JavaScript template engine that doesn't destroy events attached to the template?

I have been evaluating a lot of different client-side JS template engines (doT, parrot, dust.js, microtemplating, underscore, etc). They all work similarly, using some type of tags to represent data, and with some giving the ability to embed pure JS into the template, including loops, if/then, etc. However, they all work by converting the template itself into a string, then into javascript, in order to interpolate the variables, execute loops, etc.
When this conversion happens, any event handlers that were attached to the original objects within the template (i.e. created by jQuery at document.ready) are of course lost. To add these handlers back to the resulting HTML would then necessitate going back and re-applying any such event handlers after each template rendering.
I'm trying to think of a way to create a template engine with full javascript support, but which preserves any events attached to the template before cloning.
Imagine a scenario where the template is for a list of items. Each item includes buttons which perform specific tasks on that item (i.e. edit, delete, rename, copy, you get the idea).
To make the code clean and easily maintainable, it would make sense to apply Click events to these buttons in the template HTML at document.ready(). Then each time the template is cloned for a new list item, the events are cloned too.
However, with current templating libraries, all events are lost at the cloning stage, which necessitates applying all events to the cloned object each time the list is updated. If this is live data, or if the user is adding new items to the list, this seems like it would become very convoluted to keep track of the events and ensure they are properly attached each time an item is added.
I know jQuery has a clone() function which clones events, and this works great for basic templates, but when you get try to incorporate arbitrary JavaScript into the template, this becomes impractical.
I am trying to avoid templates which depend on html element attributes to configure loops, decisions, etc, because the template code becomes very ugly. A clean template with simple tags for data substitutions, simple JS for-loops for repeated elements, and simple references to the source data, is desired.
Anyone have ideas on how to do this?
Instead of over-complicating templating, you should use event delegation, so that this problem does not even present itself.
And yes, jQuery had .delegate – it is deprecated, and has been replaced by .on, which can do the same thing, see http://api.jquery.com/delegate/#entry-longdesc

Is a component bound to just one element?

I'm trying to wrap my head around Twitter flight. Lets say I have a Program page, it has 16 elements dealing with managing a program, CRUD operations, AJAX requests etc... Using twitter flight, do i need to create a component for each and every node element or for the Program page and attach each element to a function in the Program component?
A component is instantiated for each element you attach it to. If you have a list of DOM nodes, you can call .attachTo on each one and instantiate a set of components for all the nodes.
You don't have to attach a component to every node. You could have a single component attached to the document which does everything, but it makes sense to break that down in to smaller pieces of functionality. IMO, a component should represent a feature.
For example, you may have a component which communicates with an API via ajax, another which handles submissions for a particular form, another which manages the content of a list. Just how much a single component does is up to you. For the sake of portability, reusability and ease of maintenance it makes sense to keep components small and well-defined.
Saying that, you probably don't want to make lots and lots of tiny components. I wouldn't want to create one for every item in a list, but I might create one for every list on a page.
A single instance of a component can be attached to a DOM node. Components have access to the full DOM tree extending from their root node.

backbone.js - How are models/views linked to DOM element?

I'm just playing around with backbone.js and some jQuery magic to prepare for some upcoming projects.
One test case contains a table whose rows are rendered by a backbone view. They get perfectly re-rendered on value change. Afterwards the whole table is sorted by an jQuery plugin (Animated Table Sort), rows move to new positions. In fact, this process works once, but the next time, rows appear twice, everything ends up in chaos.
Is it possible, that the link between DOM element and backbone view can't handle such an change? Are there any workarounds?
When you're developing with a Model/View framework like backbone.js or knockout.js, I find that you need to re-arrange your thinking and implementations to make changes to what is diplayed (like sorting) to the Model, and not allow them to happen in the view (like using a jquery plugin).
If you do end up using a view-side script to do something fancy (animations are a good example), then it is up to you to make sure the model is updated correctly, either by disabling or extending the binding.
Also note that according to the documentation, that animated sort plugin removes your table rows from the DOM, adds them to new DIVs, animates them, removes them from the DIVs, and restores them to the table. I'm wondering if after this is all done, backbone has lost track of those TDs, and when it re-renders after the change, it's just adding a new set since the last set is 'gone'.
Thanks for your answers. Indeed, the table sorter does a lot that makes it difficult fpr backbone to maintain bindings. I've switched over to the great Quicksand plugin which uses a hidden list to animate changes in another (visible) list. Fits better to backbone.js.
Your collection maintains an order for your models, and therefor your corresponding views. If an outside force (like a jQuery table sorting plugin) modifies the order of the views, this change is not inherently reflected in the Backbone collection, so things are quickly out of sync.
Also, if the table sorter clones elements and removes the original, Backbone would likely lose track of the views and end up recreating them.

Categories