content does not matt...">

AngularJS - My Partial Controller

I have a template that is repeatedly added to my DOM.

<div ng-controller="theController"> content does not matter </div> 

Thus, the controller is repeatedly corrected. This is a problem because if I put an observer in the controller

 theController = function($scope) { $scope.$on('myVar', function() { // run one time for each time the template is repeated }) } 

Any ideas on how to avoid this? Thanks in advance.

UPDATE

OK, I will try to be more clear.

Perhaps I have a form that is built dynamically based on the response of an asynchronous request.

 <form ng-controller="formController"> <div ng-repeat="f in fields"> <ng-inclide src="f.fields"></ng-include> </div> </form> 

A controller is something like:

 function formController($scope) { $scope.fields = [{ template:'', ... }]; // data come from an ajax request... // here are static for the sake of simplicity. } 

Therefore, I do not know which fields will be added to the form.

The structure of the form field is stored in html elements ... something like:

 <div ng-controller="inputController"> <label> .... </label> <input type="text" .... /> </div> 

or

 <div ng-controller="selectController"> <label> .... </label> <select> .... </select> </div> function selectController($scope){ $scope.$on("myCustomEvent", function(event) { cionsole.info("Options were updated"); }); } 

If the form has more than input type=text , or select , inputController or selectController created more than once.

Why don't you want $ watch to occur for every instance?

I would like to update the parameters of one of the options on the page when a certain event occurs.

Instead, I want to update everything on the page.

From the comment, I realized that it is wrong to have more elements with the same controller on the same page. So, currently the only solution available seems to be to avoid defining a controller for each form element, right?

UPDATE 2

$emit used in inputController :

 function inputController() { $scope.fireclick = function(p) { if (p == 'specificInput') { /* this is a temporary work around I used to bind the event only with a specific field */ $scope.$emit("myCustomEvent"); } } } 

This is the complete code for the input field used in the html part:

 <input type="text" ng-click="fireclick(f.name);" name="{{f.name}}" /> 

@Anybody:

It’s possible to at least confirm (and, in the end, say why) in order to have more elements on the same page with the same controller.

+6
source share
3 answers

Here's how I managed to create a form with recursive fields (based on this SO answer: fooobar.com/questions/81747 / ... )

Result [ link to image ]:

enter image description here

View controller which loads the particle Home.html using ng-view:

 app.controller('HomeController', ['$scope', '$http', function ($scope, $http) { $scope.msg = 'Home Page Message'; }]); 

Form controller which is inside Home.html:

 app.controller('NestedFormCtrl', ['$scope', function ($scope) { $scope.formData = [ {label:'First Name', type:'text', required:'true'}, {label:'Last Name', type:'text', required:'true'}, {label:'Coffee Preference', type:'dropdown', options: ["HiTest", "Dunkin", "Decaf"]}, {label: 'Address', type:'group', Fields:[ {label:'Street1', type:'text', required:'true'}, {label:'City', type:'text', required:'true'}, {label:'State', type:'dropdown', options: ["California", "New York", "Florida"]} ]} ]; $scope.$watch('formData[3].Fields[1].label', function(newval, oldval) { if (oldval !== newval) { console.log('watch', oldval, newval); } }); // this was added after and is not shown in the image $scope.$watch('formData', function(newval, oldval) { if (oldval !== newval) { console.log('watch', oldval, newval); } }, true); $scope.changefield = function() { $scope.formData[3].Fields[1].label = 'Postal Code'; } $scope.customevent = function(field) { var type = field.type; // do something for this type console.log('customevent', field); }; }]); 

Partial home browsing (here the template path in ng-include may be a property of your fields or you can use the switch case and display the input / selection of your choice:

 <h1>{{msg}}</h1> <ul ng-controller="NestedFormCtrl"> <li><button ng-click="changefield()">Change</button></li> <li ng-repeat="field in formData" ng-include="'views/field.html'"></li> </ul> 

Field.html template (either one template for each field type, or one main template with the switch key on the field.type property)

 <button ng-click="customevent(field)">{{field.label}}</button> <ul> <li ng-repeat="field in field.Fields" ng-include="'views/field.html'"></li> </ul> 
+4
source

I think Angular's way of doing this is to use directives. I would do something like an ng switch in your main ng-repeat view, and ng-switch would just include the corresponding directive ... Assuming the "input-text" directive exists, the "input-drop-down" directive exists:

 <div ng-swtich on="field.type" ng-repeat="field in fields"> <div ng-switch-when="text"><input-text ...></div> <div ng-switch-when="dropdown"><input-dropdown ...></div> </div> 

I believe that you will not have the same problem that you are currently facing. I actually haven't set up what you are trying to do, but I'm 99% sure you should use directives! They are perfect for what you are doing and will be much more reusable.

I use the http://angularlist.com directive to process ratings, and I can say with confidence that they do not cross wires when I have several pages per page - However, I do not observe anything there, I simply respond to events ... In fact, let me check something (testing .........) Yes! I added a clock to the model value that my rating directive edits, and when I click on the rating, only ONE observer is launched - one that is designed for the corresponding controller. This is not on a real site, just my dev server is here, but a directive, if that helps you:

 app.directive("angularStars", function() { return { restrict: 'E', scope: { model: '=ngModel', notifyId: '=notifyId' }, replace: true, transclude: true, template: '<div><ol class="angular-stars">' + '<li ng-class="{active:model>0,over:over>0}">1</li>' + '<li ng-class="{active:model>1,over:over>1}">2</li>' + '<li ng-class="{active:model>2,over:over>2}">3</li>' + '<li ng-class="{active:model>3,over:over>3}">4</li>' + '<li ng-class="{active:model>4,over:over>4}">5</li>' + '</ol></div>', controller: function($scope, $attrs, $http) { $scope.over = 0; // TEST WATCH $scope.$watch('model', function() { console.log('modelChange', $scope.model); }); $scope.setRating = function(rating) { $scope.model = rating; $scope.$apply(); if ($attrs.notifyUrl !== void 0 && $scope.notifyId) { return $http.post($attrs.notifyUrl, { id: $scope.notifyId, rating: rating }).error(function(data) { if (typeof data === 'string') { alert(data); } return $scope.model = 0; }); } }; return $scope.setOver = function(n) { $scope.over = n; return $scope.$apply(); }; }, link: function(scope, iElem, iAttrs) { if (iAttrs.notifyUrl !== void 0) { return angular.forEach(iElem.children(), function(ol) { return angular.forEach(ol.children, function(li) { li.addEventListener('mouseover', function() { return scope.setOver(parseInt(li.innerHTML)); }); li.addEventListener('mouseout', function() { return scope.setOver(0); }); return li.addEventListener('click', function() { return scope.setRating(parseInt(li.innerHTML)); }); }); }); } } }; }); 

Directives are hard to deceive - I still mostly shoot in the dark with them, trying to figure out how they work, but without a doubt, the power you need is in the directives. I highly recommend reading AngularJS docs for writing directives and then spending time on other directives for people - there are many opportunities to learn on GitHub!

+5
source

Here is a plan to help you in this scenario ...

http://plnkr.co/edit/RvFrmPd4rlAM8aeFSwg7?p=preview

This is just an illustration of how this can be achieved. Not knowing how much control you have over form configuration data, it is actually impossible to provide a more complete answer. Meanwhile, if you want to know, it’s better to insert $ rootScope wherever you want to broadcast $ ($ emit goes up the DOM tree, while $ broadcast is turned off .. Thus, the transfer from $ rootScope will be available for the entire application. )

Let me know if this helps you.

+1
source

All Articles