AngularJS - Multiple non-nesting elements on a single app - javascript

I'm trying to have an app in which there are many elements spread all over the page. The highest element I could use for bootstrapping the app is the BODY element, however I do not want to do it like this.
I would like just to tell angular to bootstrap the same app over more elements which are not related in any way and share the data between it.
I've setup a plunker, however it seems that a shared service is not the right way to go
Basically, in any of the textfields you'd change the text, it should propagate to the other one as well, however this does not happen.
What I am doing wrong? Is there a better approach to this?
Thanks.

Related

Sencha ExtJS: why do menus get attached to the Viewport instead of the instancing View?

Hey I'm new to ExtJS development and development in general. I'm still in college and I'm currently trying to build the UI for a Webapp made in ExtJS and I'm having a bit of a problem with menus and how they work. I am pretty sure I'm overlooking something and there has to be a simple way to do what I'm intending to do with menus.
To be specific I have 2 menus in my App and they both give me the same kind of problem...
The first one uses code from this example: https://examples.sencha.com/extjs/6.7.0/examples/kitchensink/?modern#menus
it has a few fields that when changed then should update the main view...
the problem here is that the menu gets attached to the Viewport
this.topMenu = Ext.Viewport.setMenu(this.getMenuCfg('top'), {
side: 'top'
});
which sets the scope of the fields' listeners that are inside the menu to the viewport instead of to the instancing views' controller which then makes it hard to get to the actual components I was looking for inside my main view or even loading stores from the viewmodel attached to my main view.
in fact I had to reverse engineer it with a debugger to then find this cryptic way to my store:
var me = this,
vm = me.getViewModel().children["generated-cryptic-name-of-my-model-1"],
myStore = vm.getStore('MyStore');
and of course the problem also works the other way around...
inside methods fired from my main views' controller I won't be able to find the references of the components inside the menu with
this.lookupReference('reference')
instead I had to again find a rather unintuitive a way to my components by giving them an ID. Again I only found this by using a debugger... it looks like this:
var me = this,
menuItems = me.topMenu.getActiveItem().getItems(),
fieldset = menuItems.getByKey('fldSet'),
myField = fieldset.getItems().getByKey('myField');
because I was only using 1 menu in my entire App at first I saw it as sort of technical debt and I didnt really look into it any further because I found a workaround.
But now I added another Menu, this time to the split section of a SplitButton, as shown in the Docs(https://docs.sencha.com/extjs/6.7.0/modern/Ext.SplitButton.html)
and again the menu gets attached to the viewport instead of the instancing view, which makes the handler functions fire at the viewportcontroller and takes the ability to find the references of my components inside the instancing views with this.lookupReference('reference').
I can make the handlers fire at the right controller by setting a controller config for the menu when instancing, but I haven't found an easy way of getting my components references and it is really bugging me at this point...
I would love to hear your suggestions, cheers ;)
It would probably help to know which views, viewcontrollers and viewmodels there are. The code vm = me.getViewModel().children["generated-cryptic-name-of-my-model-1"] makes me suspect there are more viewmodels and viewcontrollers involved, and it would help to know their relations. I wouldn't be surprised if the menus are not the problem at all...

How to create Twitter like profile layout?

I am trying to create Twitter like profile layout in React Native. Although many apps use this pattern. My current JSX setup is something like this.
Header (profile)
ViewPagerNav (custom)
ViewPager
Tab with ListView
Tab with ListView
Problem is that only bottom part scrolls. I have seen this problem for many React Native apps. Is there a solution for this?
How should my render view look like to g full get page scrolling?
There is actually a really good example of this in the F8 app. The 3 files you want to look at are here:
https://github.com/fbsamples/f8app/blob/master/js/tabs/schedule/MyScheduleView.js
https://github.com/fbsamples/f8app/blob/master/js/common/ListContainer.js
https://github.com/fbsamples/f8app/blob/master/js/common/PureListView.js
If you want to see how it works in the app it is the My F8 tab.
The basic idea is that the ListContainer keeps track of the scroll position via the handleScroll function. It passes handleScroll to all of its children renaming the function to onScroll.
The PureListView a it takes that onScroll property via the object spread operator {...this.props} and passes it into the ListView.
That is all just to keep track of the scroll. If you look in MyScheduleView.js you can see how it is mostly implemented.
Hope that helps.

How to correctly interact with a view which is managed from another controller?

The question might seem too vague but I could not think of a better way to describe the idea, so I'll try to explain it in details.
I have MasterController attached to <html> tag of my SPA application. This MasterController contains all the logic and models for controlling the following UI elements:
page title (<title> tag)
subheader which displays the title of current page (like Customers, Orders, Settings etc.)
name of the currently logged-in user
some commonly used action buttons which will be used for all pages in the system. To be specific, these buttons are Show filters, Export data to Excel and Add new record.
While the first two items on this list can be managed through detection of current ui-router state (through its $stateChangeSuccess event), the last two (username and buttons) are somewhat problematic, especially the buttons.
I can manage the button actions using $broadcast, so every controller can be notified about clicks on any button. But the tricky part here is that the buttons might be needed in different combinations - one page might need all of them, and another one might need none.
Let's say, ui-router loads some CustomersController. At that point MasterController receives $stateChangeSuccess event and by default hides all the buttons.
But now, how does CustomersController tell to MasterController that CustomersController will need two specific buttons from the very beginning?
Theoretically, I could use $emit from CustomersController to send an event to MasterController, but it somehow feels ugly. Events are meant for, well, events and not for sending requests like "hey, MasterController, if you are somewhere up the scope, can you please show the following buttons?".
Of course, I might be wrong and maybe there is some way to use Angular event system to manage this scenario in clean way.
What came to my mind is that maybe in the $stateChangeSuccess event I could somehow detect if there are currently any listeners for my button click events and then I could hide buttons which do not have any listeners attached, but I'm not sure how to do it, and I'm not sure whether it will work as expected - whether old listeners will be detached when ui-router recreates the view with another controller.
If you are just nesting controllers, their corresponding scopes actually make use of prototypical inheritance. So you could just define a function $scope.configureButtons in your MasterController and call this function from the $scope in your nested CustomerController.
If Controllers are not nested you would probably need to resort to $rootScope.$broadcast for setting up your buttons.
Why not just simply using diferent controllers for each view? Maybe generalize a bit the CustomerController and extend it (specialize it) for every combination of buttons you need. Using the $stateChangeSuccess feels like avoiding polymorphism to me.
Today I got a tricky idea based on #Diego Castaño Chillarón 's answer. I thought - but is it possible to use ui-router to swap controller of existing view and will it rebind also the $scope? And will I still be able to replace inner parts of the loaded view?
It turned out that it is doable! Now I don't have to control the common view fragments from the master control, and I don't need also to inherit or duplicate them - I just switch the controller to the required one through ui-router.
Like this:
$stateProvider
.state("customers", {
url: "^/customers",
views: {
"controller": {
controller: "CustomerController as cntrlr"
},
"page#customers": // <- this is important, absolute name required for ui-router to find nested view
{
templateUrl: "customers"
}
}
}) // other routes follow in the same manner
And my HTML looks like this:
<div id="routes-root" ui-view="controller">
<div id="content-header-buttons">
<button type="button" ng-click="master.toggleFilter()">Filter data</button>
<button type="button" ng-click="cntrlr.exportClicked()">Export</button>
<button type="button" ng-click="cntrlr.createNewClicked()">Create</button>
</div>
<div id="view-content" ui-view="page"></div>
</div>
As you see, I left master controller to control only visibility for filters block, which won't change.
But controller itself is attached to #routes-root element, preserving inner content, and ui-router (or Angular) is smart enough to attach $scope and cntrlr variable to the loaded controller. And then I load inner view into #view-content, which also gets attached to the already loaded controller.

Make DerbyJS only re-render certain DOM nodes

The way DerbyJS (http://derbyjs.com) seems to work at the moment is that it replaces everything in the body tag of the document whenever you click a link.
Is there anyway to say use the template, but replace the content inside #main-content with that instead of the whole body?
Navigation on the left is fixed and doesn't need the benefits of realtime interaction.
Why this is an issue is needing to run some Javascript on the page load to set the size of some containers based on the size of a users browser window, and once I click a link, this setup gets wiped and recreated, and of course, the Javascript doesn't run again, because the document itself hasn't refreshed, just the body.
This would also allow me to write nicer jQuery bindings for the most part, $('element').click(, rather than $('html').on('click','element', ...
Any thoughts, or is this a step too far for this framework at this point in time?
P.S. As I'm only just getting started with Derby, and realtime frameworks in general, maybe what I'm trying to do isn't best practice anyway? I chose Derby because I like the UX part of initial render on the server, then the rest in the client, but sharing routers, which reduces the duplication of code. Open to any better ways of achieving this.
There is no way to rerender part of body on page reload. Just whole body.
You can use app.enter hook to run js code after every page render.
No need to use jQuery bindings, use Derby bindings
I fully agree with Vladimir's answer, just trying to add something to it.
It should be possible to re-render part of the UI through transitional routes (http://derbyjs.com/#routes). In your case it seems like app.enter is the way to go though.

How to better organize multi-views in a web single page app?

Assume I have a lot of views in my single page app. It means, I put some view inside a div and show this or that view depending on user's actions. So, I usually show on view at a time. For example, I have these views - dashboard, settings, entries, entry details.
Depending on current state of the app one of these views is visible and others aren't. When I go this way dashboard > entries > entry details, then edit some entry details and click save or back button, I want the app to go back to entries. But if I have a link on dashboard that, for example goes to the latest edited entry, I can go this way dashboard > entry details, and in this case I want to get back to the dashboard by clicking save or back button.
This case can become even more complex with deeper views paths. Right now I manage it like this - When a button responsible for views switching is clicked, the variable state is being changed to something like from_dashboard_to_entries. I listen for that variable to change, then do all the view switching from another function depending on the state variable value. This way I have to manually define all possible scenarios and test all the possible combinations of cases. Right now this approach works quite well, but I am worried about deeper, or longer views sequences.
My idea is to somehow create a history of views in an array or something but I am not clearly understand how to do it better.
Please share your thoughts how you would organize this.
Simply don't worry about the source view - you don't have to know it to change to the destination view. If you want a history, instead of manually storing it, consider using the HTML5 History API, preferably with a wrapper library (e.g. History.js).
Rather, We should be setting the view while changing the state of application. This may optimize the initial app launch time by not loading all the views at launch and will give a way for on-demand loading.

Categories

Resources