Sharing AngularJS models - angularjs

I have an Angular controller CanvasController modelling a canvas onto which "widgets" can be placed.
The controller maintains a simple array, _currentWidgets, of object literals that correspond to the widgets currently on the canvas. e.g. [ {id: 1} ].
A CanvasDirective is tied to CanvasController, with an Angular watch placed on the array currentWidgets in the link function. This means the canvas is re-rendered when widgets are added and removed.
The canvas template contains the following line to render the widgets:
<div ng-include="'widget-template'" ng-repeat="widgetModel in currentWidgets" />
And widget template is defined as follows:
<div ng-controller="widgetController as widgetCtrl">foo</div>
It is my understanding that this means that whenever a new item is added to currentWidgets a new instance of WidgetController is instantiated by Angular for use by the new widget.
My question - how can I share the model created in the CanvasController with the new instance of the WidgetController instantiated when a widget it added? Or would this not be idiomatic and should I simply instantiate a separate model for the widget inside the WidgetController?

In your case it might already be shared already. See prototypal inheritance.
As I understand your widgets should have scopes that are child to the canvas directive, right?
A quick solution is to create a method in the parent, javascript's prototypal inheritance should lookup the method from the child to the parent's.
Or send events...
The controller's role is to extend a scope, perhaps from the $rootScope.
That means your controller's scope is a child of the $rootScope. You can try $rootScope.$broadcast() or scope.$emit(). That's one way, by sending events.
$emit() will send events going upward to the $rootScope from the child scope.
$broadcast() will send events going downward from the parent to the descendants.

Related

Ionic framework with AngularJs : Can a modal have the same controller as the view that launches the modal?

I am trying to build out a multistep form for a complex object. I use the modal to section out parts of the form. The Ionic examples I could find, appear to assign a different controller to the modal. I would like to keep the view plus all the modals it launches, all of them associated with one controller. Is that possible? I tried assigning to the modal view ng-controller="viewCtrl" where viewCtrl is also the controller of the starting view that launches the modal, but it appears to hang chrome with a high CPU which subsequently necessitates killing the chrome tab.(some sort of cyclic effect by calling the same controller??)
Your advice/insight would be welcome.
I assume that your modal is a directive.
I also assume that you have it placed inside the view (controller scope).
If the above are correct than the directive inherits the $scope properties and methods from the parent controller (a general thing in angular), unless your directive has an isolated scope (if you have the scope property in the directive set to anything but false).
If your directive has an isolated scope you can still pass data from the parent using attributes on the directive. If you want to pass something from the directive to the parent you can use $emit.
You can also access the parent from the directive using $parent but I would suggest against it.

Building a reusable AngularJS directive with two-way databinding set through code

I'm trying to build a reusable directive that shows a dialog box when a button is clicked and allows the user to customize an array of strings. I have this working fine in a single-use-case scenario, but I'm trying to figure out if I can create two-way data binding through code, so that I can use a single instance of this directive multiple times with different arrays of strings.
In my HTML, I have the directive (note the lack of binding to a particular array):
<my-array-dialog control='arrayDialog'></my-array-dialog>
I'm exposing a shared control object with a showDialog method on it that causes the dialog to be shown. An example of that pattern is: http://plnkr.co/edit/MqN9yS8R5dnqTfjqldwX?p=preview
What I want to do is have two-way data-binding with the parent controller passing in the data into my showDialog method. I'm unsure how to configure this though, or even if it is possible.
In my directive, I have the following:
$scope.control = {
showDialog: function (arrayData) {
// Ideally, this would create two-way data binding
$scope.arrayData = arrayData;
// Manipulate the DOM here to show the dialog
}
}
Ideally, changes to $scope.arrayData would be reflected in the calling code's arrayData. Again, the reason I'm not setting this up as an attribute is because I want to call this dialog multiple times with different data and to avoid having multiple dialog directive instances.
Is it possible to set up the two-way data binding in this manner, or am I going about this all wrong?
Absolutely! Check out the intimidating yet incredibly helpful AngularJS docs page on $compile. In particular, what it sounds like you'd like to do is create a two-way binding between a parent scope variable and a variable in the local scope of the directive.
When defining a directive, you can specify a scope object. You'll want to create an isolate scope (for reusability) and use the # feature to create the two-way bindings with the HTML attributes.
From the $compile docs:
= or =attr - set up bi-directional binding between a local scope property and the parent scope property of name defined via the value of the attr attribute. If no attr name is specified then the attribute name is assumed to be the same as the local name. Given and widget definition of scope: { localModel:'=myAttr' }, then widget scope property localModel will reflect the value of parentModel on the parent scope. Any changes to parentModel will be reflected in localModel and any changes in localModel will reflect in parentModel.

Sharing isolate scope with nested directives in Angular

I want to have a custom directive that is reusable and creates an isolate scope so it can be used anywhere (as long as the consumer uses the API defined by the directive). Then, I want the consumer to easily be able to mix and match different reusable pieces that fit within the main reusable directive.
The situation I'm working with is a drop down menu. The main directive would isolate the scope and define the API for the dropdown as a whole. The inner directives would allow the consumer to choose whether they want a button that opens the menu, a search box/input field that opens the menu, etc. Then they could also choose what menu style is used:
<dropdown items="..." selected-item="...">
<dropdown-button>(Transcluded button text here)</dropdown-button>
<dropdown-icon-list></dropdown-icon-list>
</dropdown>
The parent directive/controller would handle state/communication for the inner pieces (ie. the button might trigger the "open" state, and the list would respond by opening). In other words, the parent directive would provide a single place for the consumer to define behavior and isolate scope from the rest of the page, while the nested directives would change shared state/respond to changes in shared state based on their role.
I actually had this working by using an isolate scope on the main "dropdown" directive and then inheriting scope with the nested directives (didn't specify "scope: ..." on the nested directives). But, with Angular 1.2, things have changed such that the isolate scope of the parent is truly isolated--the children inherit the scope that exists outside the parent directive, rather than sharing its isolated scope.
What is the Angular way to accomplish such a thing?
I've started retrofitting my existing code to share the controller from the parent directive with the nested children, but I feel that's the wrong way to go once I get into the situation where the children need to listen for changes on the shared scope... The only way I can see to do that would be to pass a callback function from the nested directives into the shared controller which it would bind to a $scope.$on method. Seems like the wrong path to head down.
There’re 3 types of prefixes AngularJS provides.
"#" ( Text binding / one-way binding )
"=" ( Direct model binding / two-way binding )
"&" ( Behaviour binding / Method binding )
All these prefixes receives data from the attributes of the directive element and provide communication between directives. please visit below link for similar question.
Visit https://stackoverflow.com/a/33024209/4348824

How to pass variables from a controller to a view and vice versa in extjs4 MVC?

I need to pass some variables from a controller to its view or to another view. How can i do this in extjs4's MVC structure?
If you are creating a object of view from controller then pass that variable directly e.g. Ext.create('view.myview',{id:Ext.id(),myVariable:"someValue"});
and you can access it in view's initComponent method as
initComponent: function() { this.myVariable }
I recommend using Passive View, where the view has as little logic as possible.
Your controller can get access to any of the widgets in the view, via ComponentQuery. You can then write code in the controller to set or read values from the view.
You can also use the form.loadRecord() method to load a model into a view/form.
The widgets in the view communicate with the controller by raising events that are then handled by the controller.
You should load all of your controllers when the application starts.
Your controller should only have event handlers, and should never use the refs array or getView() functions (else you won't be able to control multiple instances of the same view).
Create and destroy your views at will. Pass in callback functions to communicate from parent to child view.

extjs :access tabpanel scope from columnmodel scope?

Inside a tabpanel,there is a tab,in the tab there is a gridpanel. One of the columns in the grid needs to have a renderer.
The renderer needs to use a property that is defined at the scope level of tabpanel.
So from inside column model, can we access the outer scope of tabpanel?
Thanks.
There are a couple of ways of doing this, however not all are very good to use!
use Ext.getCmp(), but I STRONGLY advise you not to do so
use myComponent.ownerCt to travel up in the hyrarchy of components (from child to parent)
on construction of the child component (where 'this' is the parent's scope) create a delegate handler in the child to update things in the parent
use events to trigger actions, I usually create a singleton eventhandler in my application that allows components to communicate through the Publish-Subscribe pattern
Good luck

Resources