ngModel without providing model name in angular 2 - angularjs

<input #gb type="text" pInputText class="ui-widget ui-text" ngModel
(ngModelChange)="clearFilter($event)">
I didn't assign any model name to ngModel directive in my code, but Angular 2 accepts this, while AngularJS (1.x) doesn't. Which scenario we need to use this kind of ngModel directive without providing model name?

Angular 2 accepts it because the object could be set later. A proper way of coding this would be to check if the object exists first, and only then show the object if it exists.
For example: You are using a service to instantiate all your objects on the page. Whenever a user goes to one of your pages you do not want to let the user wait for the response of the service, but you want to show them all the content of the page immediately. The service response will instantiate the objects later and only then show them to the users.
This could be done for example by the onInit interface that Angular 2 provides. This makes sure that you can call on services and instantiate objects after the html elements are already fully loaded.
Angular2 just gives you this possibility for free because whenever the object doesn't exist, it just won't show them to the user.
The difference between angularJs (Angular1) and Angular(Angular2 or Angular4) are huge and this is just one of many examples. You could look at it this way: the only thing the two frameworks (AngularJS and Angular2) have in common is that they share a couple of the same letters.

Related

Context dictionary from Django template to Angular

I am building a web app and I want to know what is the best and the safest way to pass a variable from a django context dictionary to Angular.
I have access to a variable of the context dictionary from Django template. Should I use ng-init to pass that value to an Angular variable?
It is about a user profile page and I want the user to be able to update his Data. The Data is initialized when calling the view but when I want him to update that Data i want to post using an Angular JS variable.
Thanks in advance
I would add the data as the initial value of each form tag. This answer has a useful "initial" directive to do it in a way that would allow you to use the form even without Angular.
<input name="profile[name]" value="Joe" ng-model="profile.name" initial>
With that, Angular would take the initial value fro the value attribute (as it should be), so that your form would have an initial value even without Angular running.

Is it bad practice for an angular directive to request data

Consider for example a currentUser directive.
I could let the controller use a service to get the data about the current user, provider it to the directive and let the directive render some "hello {user.name}" template.
Alternatively I could have the directive have a dependency on some currentUserService and in the directive's controller ask for currentUserService.getCurrentUser.
Is one of the two significantly better then the other for any reason?
I tend to go with the first option but not sure if the using the second one would not have a benefit of having all the current-user-logic less spread around...
Thanks
As long as you're requesting the data from a service, I believe having a dependency toward it in a directive is fine.
The main aspect of the controller is having access to $scope, not much more.
There are two scenarios and it really depends on the purpose of your directive:
the directive is only used to display user-data (in a complex way)
the directive displays data and manipulates it (according to user-input)
SCENARIO 1
Since the only purpose of the directive it to render the data somehow, the directive should not be responsible for retrieving the data.
So you decouple the logic how to access the data and how to display the data. This way you can also use the directive for users other than the currently logged in user.
If there should be some special things visible, if the user is logged in, the directive should use ng-if or ng-show for that (and maybe a parameter to disable that view-part).
SCENARIO 2
In this case the purpose of the directive is to provide a gui for some business-logic (service functionality). Therefore the service should be injected into the directive.
Remark:
PERFORMACE
If you get the data via method-call from your service, this method will only be called once in every digest-cycle if you load the data and inject it into the directive-controller. Otherwise it may be called once for each occurance of the directive.
INTEGRITY
Remember, that if your service-method requests data via http and you are using the directive for example 3 times in a view and the directive calls the service-method itself, this will result in 3 identical requests which may have non-identical results (i.e. someone other changes the data while the requests are processed).
It is always better to use service to reside business logic.You should use service to get data and inject that service to directive.Do not use controller to communicate between directive.Service is meant for that purpose, initiate once.

Angularjs dynamically added ng-model is not accessible by $scope, shows undefined

I am creating form, where few fields are dynamic, ng-model is added dynamically.
Ex.:
form.append("<input type='hidden' name='paymillToken' value='" + token + "' data-ng-model = 'formdata.token'/>");
This fields shows undefined while I try to access using $scope.formdata.token
Following is another scenario where I am adding fields via ajax.
angular.forEach(data.data, function(obj, key) {
list+='<div class="items text-center"><img src="assets/uploads/discs/'+obj.image+'" class="img-circle"><br><input type="radio" id="chkDisc'+obj.id+'" name="disc_id" value="'+obj.id+'" required data-ng-model="formdata.disc_id" /></div>';
});
$scope.discslist = $sce.trustAsHtml(list);
This model disk_id is not accessible too.
Okay, to expand on my comment and a bit more on what everyone else here is saying to you, the main issue you're having is inherent in your approach. The way you're trying to manipulate the DOM is very un-AngularJS.
In AngularJS, when you want to change what is displayed to the user (the view), you make changes to your model (your controller scope). That means, you have to set up your view to be able to respond to those changes. We do that with directives and expressions in Angular.
You're probably already using directives to respond to changes in your model whether you realize it or not. ngRepeat, ngModel, ngShow, ngIf, ngInclude, are a handful you're probably familiar with, and even forms and form elements like inputs are actually directives in Angular. When you use these, a change in your model (such as loading data into the controller scope) signals to Angular that it should check whether that change affects any of the directives in your view, and if so, respond to it by updating the view.
In order to do this, Angular needs to know which parts of the model are connected to which parts of the view. It makes these connections when it compiles the html elements that are added to the page. This compile process happens automatically when you load an Angular app. After that, it's up to us to tell Angular when to compile html that is added to the page.
More often than not, we do this without even realizing it. For example, when you use the ngView directive, it will compile the template for each route that it loads, so that all of the directives in your template are properly linked with their associated model.
I know this is a long explanation, but there are two very important points here that are essential to learning AngularJS:
To change the view, you change your model and let the directives (and expressions) on your page respond to those changes.
When you add html elements to the page, if you want AngularJS to be able to use them in your view, they must be compiled first. The compile process should be done via a directive (either a built in one or a custom one).
So, how does all of this apply to your question?
First, I'm guessing that you're breaking both rules by trying to manipulate the DOM via a controller. Even if it is possible to use $compile in a controller, using a controller to change the DOM is bad practice and simply wrong to do (read the part in that link to the doc that specifically states: Do not use controllers to: Manipulate DOM...). A good rule to remember when you're learning AngularJS is that the only time you should ever be using JQuery or JQLite inside Angular is when you are creating a custom directive.
Okay, so how do you solve your question? Use a directive. It looks like you've got a case where you're trying to iterate over an object called data and add some inputs that correspond to the data.data property. This sounds like a job for ngRepeat.
The first thing you need to do is add your data to your controller and make sure it is accessible to the view. The easiest way to do this is by injecting $scope into your controller and setting the data on a scope variable. In its simplest form, that might look something like this:
angular.module('MyApp', [])
.controller('MyController', ['$scope', function($scope){
$http.get('/some/url/that/returns/the/data').
success(function(data) {
$scope.data = data;
});
}]);
Now that we have the data somewhere that we can access from the view, we can use it with the ngRepeat directive in our html, something like this:
<div ng-controller="MyController">
<div class="items text-center" ng-repeat="disc in data.data">
<img ng-src="assets/uploads/discs/{{disc.image}}" class="img-circle"><br>
<input type="radio" id="{{'chkDisc' + disc.id}}" name="{{disc.disc_id}}" value="{{disc.disc.id}}" required data-ng-model="formdata[disc.disc_id]" />
</div>
</div>
This is a common issue. By updating the value and not the model angular has no idea that the value in the field has been updated. As the first commenter said updating in this manner is completely unnecessary when using ng-model.

Routing with Component-based Directives in Angular 1.3?

I have a question about the best way to structure the flow of an app using Angular 1.3. I'm trying to incorporate the 'Component-based Directive' approach as per guys like Matias Niemela (https://www.airpair.com/angularjs/workshops/component-based-directives-angularjs). He says in a video to still use controllers for routing rather than going completely controller-free, but to use directives to create reusable components that have all their dependencies injected.
I'm a bit new to Angular but have used Java mvc frameworks before where a controller written in Java first finishes getting the data needed on the page to be displayed, before some html is constructed and served up. I'm wondering if I'm coming a bit unstuck due to the asynchronous nature of the javascript calls used in Angular, maybe assuming things happen in an order they can't be guaranteed to....
I want to try to make the directives involved have anything they rely on injected (likely via attr's) for increased test-ability etc.
I had envisaged something like the following, for a simple customer listing, with clicking on a single customer in that list going through to a customer details page:
1) a route is defined with a target html page and a controller.
2) The controller gets the list of customers (ideally via a service), which is then available to the html page via Controller As (so Controller MyController As myCont, means the list should be available via something like myCont.myCustomers
3) A Directive is defined to display a customer row's details (name/address, plus a clickable link that passes the customer number as a parameter to a details page)
4) The html page has an ng-repeat to display all of myCustomer in myCustomers, using the Directive. So, I would want to pass the single customer details into the directive via Attr's (for my dependency injection) and then get them displayed for each customer...
(Alternatively, of course, the directive could take in all the customers and display all of them)
So, my question is really whether this is the correct approach to take, or am I missing something about the way these apps need to flow? I've tried unsuccessfully to get it working (posting this from home and my attempt is at work... I'll post the attempt if ppl think it valuable, but really my first question is about whether my overall approach is inherently flawed or not)
And then, secondly, to get the data for each customer passed to the directive, I'm assuming I need to pass the fields in in the html page that has the directive in it, passing something like {{ myCustomer }}... is this correct? (can I assume the Controller will have finished getting all the data before the ng-Repeat tries to cycle through all my customers and send their data to the directive, or not, in which case should I be passing the data via some other mechanism?)
I can't seem to find any examples on the web that tie together Component based Directives, with routing via a Controller, passing data from that controller to the directive, so any help is greatly appreciated!
Thanks!!

Best practice to pass data from a controller to another non child or parent controller?

I'm fairly new to angular, after using a video tutorial and reading some documentation, I decided to rebuild an old app of mine as an example with angularjs.
So this app has a table showing some data. It has a form underneath which helps you modify the data from the list. You have a button on each line which allows you to edit the line, it then fill all the fields in the form and you can then save or cancel your changes.
I made a controller to handle the list, it works fine, it gets a json from http.
I used ng-click on my edit button to trigger a function in this controller, giving it the whole object it's supposed to edit.
I made a controller to handle the form in which the edit should take place and I don't really found a 'non-hacky' way to pass the data from the list controller to the form controller.
So, my question is : what is the best practice and/or the common way to get this data from my list controller to my form controler ?
It depends how you are using the form controller. If it's being used within a template using ng-controller attribute, then this controller has access to parent scope, so you can work with list controller's data. (although note some scope-inheritance quirks solved by "dot notation", explained nicely by egghead.io: https://egghead.io/lessons/angularjs-the-dot)
If you're launching your edit form in a another url (e.g. /items/2/edit) and handle it in a routing configuration, then you can use resolve property to pass any data to the controller: $routeProvider docs.
You can pass the entire object as parameter
<row ng-repeat="theModelInRow in modelList" ng-click="edit(theModelInRow)">
if form controller isn't a nested controller of list controller on view, then you can use rootScope.

Resources