How to work with controllers for Extjs deeply nested components? - extjs

I have a large scale application with lots of views, models, stores in it. Till now i am able to manage all the functionality to run from functions, events withing the views itself. I have never used controller to handle the entire application.
Please let me know how to use controllers to handle each and every component in the app. And there are some components that are dynamically being generated. How to add listeners these components on demand.
Please tell me about controllers much!
Thanks in advance :)

Controllers use event selectors to handle events through an event bus, so handling events is built in to the component structure.
A controller typically looks like:
Ext.define('MyApp.controller.Foo', {
init: function() {
this.control({
'some_selector': {
someevent: this.onSomething
}
});
},
onSomething: function() {}
});
The selector is an Ext.ComponentQuery selector, so if a component that matches that selector fires a particular event, it will call your method. There's plenty of information about selectors in the docs.

Related

Using Inheritance with AngularJS Components

I am using AngularJS components in anticipation of eventually moving to Angular2. I have a component (Component1) that is essentially a dropdown with a few specific inputs and outputs. I have another component (Component2) that is the exact same kind of dropdown, but has a dependency on the ng-model in Component1. Is there a way to use inheritance in Component2 so that I do not have a bunch of duplicate code?
I can see how to use inheritance in Angular2, so this seems to be the best approach. However, I can't find anything showing how to do this in Angular 1.5.
Component1 also requires a template, but it will be the same for both Component1 and Component2. Also, Component2 will require an additional input for the value from Component1, as well as some code in the $onChanges event when that additional input changes.
Thanks in advance!!
the best thing you can do is pass a model object to component 2 as bindings,
app..component('component2', {
bindings: {
modelObject: '<'
},
controller: function () {
//do stuff
}
});
inside html
<component2 model-object="$ctrl.modalObject"></component2>
when change occures in component1. if your component depends on that change
you need to use onchanges lifecycle hooks components.inside component2 controller
this.$onChanges=function(data){
//this data has all changed values..
// you can also use isFirstChange() to determine if it was the first or not.
if(data.hasOwnProperty('modalObject'){
if(!data.modalObject.isFirstChange()){//means its not the initialization}
}
}

How React Component expose data to external app?

Let's say i have a React Component <forecast id="test"/>. And i want import this component into a legacy project which only have jquery involved.
Is it possible to get the value of this component like document.querySelector('#test').value?
I got some information from React website, that we cannot access data from outside the component. The recommended way is dispatching data from inside of the component.
My question is, the way to dispatching data is behind of the component implementation. Is it means that i have to read the source code of component in case i don't know how it works?
If this is true, i won't think React is free to inject to any product, it cost too much.
If you want to inject some React to your project you should do it with some independent part of your system.
If you have tightly coupled code base its always high cost to add any new technology to it. So its not a React problem. Try to find some independent module or subapplication in your system and move it to React. If you cannot find one, try to refactor existing code first.
You need to write a plain JS wrapper to do it. Something like this might work
function Forecast(element) {
this.value = initialValue;
React.render(<forecast onChange={onChange.bind(this)}/>, element);
function onChange(newValue) {
this.value = newValue;
}
}

Backbone Events or Routes?

Since backbone provides two ways of responding to certain events, I was wondering what the general consensus. This is a very common situation - I have a link on a page, i can set up the href on the page to route it so the router can call a function to handle it, like so:
HTML
<a href='#posts/2' class='handleInView'>Item 2</a>
JS
var AppRouter = Backbone.Router.extend({
routes: {
"posts/:id": "getPost"
}
});
or I can respond to the event in the View like so:
var MyView = Backbone.View.extend({
...
events: {
"click .handleInView": "open",
},
...
open: function() {
...
}
});
I know routes provide you with the added benefit of history and direct links, but from a performance standpoint and code layout perspective what is a better approach if I dont care about history.
My routes could be a single place where i can see all of the interactions but it also could get cluttered very quickly.
If you don't care about history or bookmarks, events have fewer side effects (people won't try to bookmark them and they won't interfere with your history) and they're simpler / faster to implement and handle.
Performance-wise, they're slightly faster as well (but really neither method is slow enough to matter at all).
I agree with the comments. Anything that requires deeplinking, bookmarks etc should be handled by using routes. However if you have something like a TabView, or another view that should be inaccessible from a URL, and is nested in another view, then it might make more sense in dealing with that inside of your view code. As for the clutter, you might want to think about reorganizing your routes into separate files. Here are some examples
Backbone general router vs. separate routing files?
Multiple routers vs single router in BackboneJs
In general, routes are used when you are calling a drastic change in the state of your application, or you would like to maintain a browsing history (via backbone.history) so the user can navigate back & forth between states via the browser buttons.
Ideally, you would use both in different circumstances.
I like to think of it in terms of what is changing on my page. If the general page state is the same, but certain elements are changing or updating, I will use events. If the general page state is changing or if I'm loading a different UI Screen, I will use routes.

Should the backbone router or view handle fetching data and displaying loading status?

In many places in my app the following pattern happens:
User clicks some link triggering navigation
Data needs to be fetched to render the view
UI design requires a "loading" spinner to be shown while data is fetched
Once the data is fetched we show the rendered view
I have tried both of the following implementation patterns:
Router handles fetching
Router tells the container view to show the loading spinner
Router loads any collections/models
Router tells the container view to hide the loading spinner
Router passes the collections/models to the view and renders it
View handles fetching
Router just creates and renders the view
The view fetches the collections and models it needs
When the view is first rendered, it just shows the loading spinner since the data is still loading
When the data arrives, the models/collections fire events and the view is bound to those so it re-renders itself, thus hiding the loading spinner and showing the full view
I dislike #1 since the router becomes a gigantic ball of Model/Collection fetching logic and seems to have too much responsibility. #2 seems like a better allocation of responsibilities (router just decides which view to show, view figures out what data it needs to fetch), but it does make the view rendering a little trickier since it's stateful now.
What does the StackOverflow community think? 1, 2, or something else?
This post is pretty old, but we were reviewing it earlier today, so in case anyone else comes across it:
To me, I really see 2 separate questions:
Where should the mechanics of data fetching and the resulting view rendering happen, in the router or a view?
Should views expect already resolved models, or should they respond to models that may still be loading?
A bit of how we handle it mixed with some personal preferences:
Neither, although I'd lean closer to the router.  Routers should handle routing, views should handle viewing, and something else should handle the mechanics and workflow of Model/Collection fetching logic.  We call that something else a Controller, which the Router basically delegates to.
As Yuri alludes to, 'sometimes' is a reality.  I think this is probably a case by case decision, but should ultimately be a contract between a Controller and View, rather than between the Router/View.
I like Yuri's bullet points, with a couple caveats (indented bullets):
The router only knows where to send the user
The outer view only knows what the user should be viewing (given its data)
Assuming the outer view is specific to the inner view's use case and is 'owned' by another view (for clean up)
Otherwise for generic containers(like rendering into a 'main' location), we've found it useful to have a component that manages the views for a certain 'section' on the page - we call it a Renderer
The inner views only know how to show only their little piece of it all (and
can be used elsewhere)
and The render function always shows the right thing as of right now.
In the case of a generic container, it'd ultimately be the responsibility of the Renderer
The main reason for the Renderer is to handle things related to that section, like cleaning up existing views to avoid ghost views, scrolling to the top on render (our MainContentRenderer does that), or showing a spinner in this case.
A psuedo-code-ish example of what that might look like, for:
a generic content target 'main' (if it's use case specific, may be better off with a ComponentView as per Yuri's example, depending on your view lifecycle management strategy)
a model we have to fetch and wait on
a view that accepts an already loaded model
Router:
routes: {
"profile": "showProfile"
},
showProfile: function() {
return new ProfileController().showProfile();
}
ProfileController:
showProfile: function() {
//simple case
var model = new Model();
var deferredView = model.fetch.then(function() {
return new View(model);
};
MainContentRenderer.renderDeferred(deferredView);
}
MainContentRenderer:
var currentView;
renderDeferred: function(deferredView) {
showSpinner();
deferredView.then(function(view) {
this.closeSpinner();
this.closeCurrentView();
this.render(view);
}
},
render: function(view) {
currentView = view;
$('#main-content').html(view.render().el);
}
closeCurrentView: function() {
if (currentView and currentView.close()) {
currentView.close();
}
}
Introducing a Controller also has the added benefit of testability. For example, we have complex rules for performing searches around URL management, picking between a results view and a new search view, and picking between a cached 'last' search result and executing a new search. We have Jasmine tests for the controllers to verify that all that flow logic is correct. It also provides an isolated place to manage these rules.
I tend to use the second option with three views, the container, a loading view, and a content view. That is, the container is instantiated by the router and during each render it looks at what it has on hand to display—sometimes provided by the router, sometimes by itself—and decides what view(s) to instantiate. A simplistic, contrived example:
ContainerView = Backbone.View.extend({
initialize: function (options) {
options.data.bind("reset", this.render, this);
},
render: function () {
var view;
// If the loading view is only shown once, e.g., splashing, then isReady()
// may be better here.
if (this.options.data.isLoading()) {
view = LoadingView;
} else {
view = DataView;
}
this.$("div.content").html(new view().render().el);
}
});
I like this approach because:
The router only knows where to send the user;
The outer view only knows what the user should be viewing (given its data);
The inner views only know how to show only their little piece of it all (and can be used elsewhere); and
The render function always shows the right thing as of right now.
Clarification:
The purpose of the view, in this case, is to understand how what is has to show should best be shown to the user. In this case, a bit of data still loading is best shown with a loading view, while ready data is best shown with a data view. Most real views are actually composing their display with many more views, e.g., depending on the user authorization different action containers.

CakePHP - centralizing controller logic

Using CakePHP, I am finding that I'm duplicating some code between controller actions. I have a dozen or so actions (belonging to various controllers) that all need to run the same query and set() the same 10 variables for the use in a particular layout. They also need to handle any errors in the same way and render an error page.
I know that components are intended to centralize logic used among controllers, but in my case, this logic needs access to the set() and render() methods of the controller. What is the suggested approach to this situation?
Thanks, Brian
Put the logic in your AppController class which your controller should extend from.
Check out the docs: http://book.cakephp.org/view/957/The-App-Controller
Ended up rolling my own sort of business logic layer on this one. Example below. Thoughts/comments welcome.
class MyController extends AppController {
public function my_action() {
// The BLL class is specific for this action and gets the entire
// controller so has access to the set() method as well as components.
$this->Bll = new MyActionLogic($this);
$this->Bll->do_whatever();
}
}

Resources