Dynamically added attribute doesn't work in angularjs - angularjs

I have a simple form with two input boxes of number type. When i try to add max attribute via directive, it seems to ignore it and doesn't validates although attribute is added on the dom element. When i add it inline it works.I referred this question AngularJs can't read dynamically set attributes but that did'nt seemed to help me.New in angularJS and completely clueless.
Any help appreciated.
Edit: Updated fiddle
Demo http://jsfiddle.net/tNUNh/6/

Didn't look furthuer, but one solution you have is to recompile the element everytime you change its max value.
Just change inject $compile (module.directive('type', ['$compile', function ($compile) {) and after attr.$set('max', '100') call $compile(element)(scope).
This doesn't seem right, but I'd need to look further into input directive code to see if it exposes a way to change it without recompiling.

Related

Angular multiple directives error on md-datepicker

I'm making a dinamic list of dates. The user can adds all datepickers he wants, but I have to validate that there are not matching dates, all of them have to be different, that's the only requisite.
I've made a custom directive validation and it's triggered correctly, but when I try to use its isolate scope, I just get that error (Multiple directives). Other questions/solutions that I've seen here, propose to delete the isolate scope, but I need it to pass to the directive the array of dates and to be able to compare them with the current selected.
Here is a codepen that reproduces the problem. If you remove the noMatchingDates directive's scope, the error just disappears and you can see and add datepickers properly. I mean this scope:
scope: {
getAllDates: "&allDates"
}
I think that it has to do with this line in docs:
Multiple directives requesting isolated scope.
And it probably also has to do with the md-datepicker which would have more directives using the isolate scope. So, how can I solve this error (and still being able to send the dates list)?
If it can't be solved (keeping the scope) given the nature of the md-datepicker, how can I reach this dynamyc validation? I think it could be done using a controller and the ng-change, but I'm not sure if it would be a proper solution.
Indeed there is no reason for your directive to require an isolated scope. Use isolated scope when your directive is like a reusable "visual component". Your directive is about logic validation and shouldn't prevent another such component.
To fix your problem, you can remove the isolated scope and use your directive in the HTML this way:
<div ... no-matching-dates="overtimeList">
Then in your link function, you can retrieve the value of that attribute this way:
var dates = scope.$parse(attr.noMatchingDates);
This will give you the content of what is bound to no-matching-dates, so in this case it will return overtimeList.
I have never used the ctrl.$parsers.unshift syntax, but it seems that you can also use it to retrieve that value. Simply remove the scope.$parse line that I just gave you and write:
ctrl.$parsers.unshift(function(arrayOfDates) { ... })
This should work as well. Note that in the first approach you need to $watch for changes if you want to run the validation every time.

problems with dynamic content in AngularJS

I use Angular to operate on table and I have a button to delete a row. I have also written a directive to it. The problems is when I add some new rows dinamically also using Angular the buttons don't work. I read a little bit about it and found out that I should use $compile, so I did. But something is wrong and doesn't work. Here comes the plunk which, I hope, will clarify my problem:
plunker
could you tell me how to make it work?
you have a mistake in $compile. You simply compile wrong html element here is Plunker

Angular directive failing silently (directive rendered too soon?)

I have an Angular app with a custom element directive (<uber-table>). <uber-table> is supposed to take a collection of objects, render them into a <table> and add some functionality (click row to toggle the underlying object as selected, search box for live filtering, action links on each row with customized click callback(s) for each object). I created a Plunker with the relevant code. Please note that Plunker is giving an error about map (Object [object Object] has no method 'map'), but locally I am not getting any errors.
The post-link function's element parameter is not the <uber-table> element as I expected. Instead it is the template's <div class="uber-table"> element. This is preventing me from extracting data from <uber-table>. What am I doing wrong? Any help will be much appreciated.
Here's a rundown on some of the issues.
First main issue is you want existing content already within the uber-table markup to exist, as well as a new template. Unless told otherwise the existing content ( columns) in this case will be overwritten. In order to include existing content in a directive that has a template, you need to set transclude:true then identify within template where this existing content needs to be placed using ng-transclude on element that will be parent of the content.
Here's demo with transclude fixed
New problems arise now where you are trying to use jQuery to loop over columns and return angular attrs => column.attrs . This throws undefined error.
I haven't tried to unravel this enough to sort out the columns issues yet. They should likely be handled by directive of their own
UPDATE: here's slightly revised error free version using jQuery to parse column count. I'm afraid am still confused a bit by structure of this. I don't see need to use jQuery to parse colunms, this could be converted to directive or pass column definitions into main directive from controller scope
After trying several things and looking at the documentation again, I finally got it working. The solution was to put the post-link function inside the compile function. Also I had to update my isolated scope to use =, set replace to true and set transclude to 'element'.
I updated Plunker if anybody wants to see the changes. The Plunker version isn't working, but since it is working locally, I'm not going to spend too much time on it.

Dynamically creating an ng-switch inside a directive

I'm trying to create a new directive that selects among several children using an ng-switch. This example is not much more than creating an ng-switch inside a directive, but eventually the directive will have more display sugar and some automatic functions so it seemed that creating a directive was the right solution.
My progress so far is in this plunker:
http://plnkr.co/edit/yeCiIOCQswYJHyTozQUZ
The $compile I'm doing seems to be evaluating the switch, and determining that the value doesn't match any of the when clauses which shouldn't be true. You can see that by inspecting the elements in the rendered picker.
I'm also concerned that calling $compile at this stage seems to have thrown away the item list, so it seems like I'm barking up the wrong tree.
How do I get the transcluded content to re-evaluate within the current state?
Update
I think I was barking up the wrong tree. Mathew's answer got me started in the right direction, so it was a big help.
As far as I can tell trying to construct a directive (ng-switch) inside a directive is a bad idea. In the previous plunker when the compile happened the template was changed permanently. That means if I changed the which parameter it wouldn't update. That's what was smelling funny to me in the first place.
Here is a revised plunker:
http://plnkr.co/edit/WUVgdXjwedxO4356321s
In this case, there's a watch on the 'which' value that refires the transclusion. That function removes the previous entry (if any) and adds the new one. There's a couple added benefits.
First I removed the 'item' directive. There's no reason for it to exist, since I'm just looking at the class. Second, I used $animator to do the list manipulation. That means you can add ng-animate to the picker and get animation effects.
I hope that helps someone else looking at this question.
There were two problems with your code:
1) Your template had which being evaluated so your on was becoming the number 1, instead of the variable you wanted which is "which":
template: '<div><div ng-switch on="which"></div></div>',
2) When you used compile, you needed to pass in the $scope like so:
$compile(sel)($scope);
Here's an updated plnkr for you: http://plnkr.co/edit/Q6ViJBvkLwQRgUKYMfS9?p=preview

AngularJS - ng-bind-html-unsafe and ng-model Problems

I have the following line in my html:
<div ng-bind-html-unsafe="departmentConfig" class="control-group"></div>
and I use a $resource get to retrieve the HTML, assign the HTML to $scope.departmentConfig, and then the view is updated perfectly. The HTML that is assigned to $scope.departmentConfig contains form elements, with ng-model attributes in it, but when I change the values in these input elements, they don't update the $scope model at all.
This is what I have tried, based on a lot of other internet posts, and it isn't working:
$resource('resources/sources/departments/:mappedName', {
mappedName:departmentKey
}).get(function(departmentConfig) {
// This will call another function that will build a chunk of HTML
$scope.departmentConfig = $scope.buildDepartmentConfigHtml(departmentConfig);
// This is my feeble attempt to access the element, and bootstrap it to include the items in the $scope model.
var $departmentConfigContainer = $('#departmentConfig');
angular.bootstrap($departmentConfigContainer, ['sourcemanager']);
I have even seen some jsFiddle examples where this appears to be working, but mine isn't. Am I calling bootstrap too soon? I also tried putting a $watch on $scope.departmentConfig like this:
$scope.$watch('departmentConfig', function() {
var $departmentConfigContainer = $('#departmentConfig');
angular.bootstrap($departmentConfigContainer);
});
but it didn't work either. I bet there is an easy explanation to this, I just can't seem to get the input elements with ng-model that are loaded after page compile to get bound to the model. Any help is appreciated, this is the last piece of functionality I need to get working on my page. Let me know if you need more information about my configuration as well.
So, simply put, how can I force a section of the DOM to recompile after I know it has been loaded?
UPDATE
Here is a jsfiddle outlining what I would like to do: http://jsfiddle.net/j_snyder/ctyfg/. You will notice that property two and three don't update the model, and I am calling bootstrap on the outer div, hoping that will include those in the model binding. This is the first time I have posted to jsfiddle, please let me know if you can't see the example.
ng-bind-html is made for regular HTML, not compiling new angular elements.
You will have use the $compile service.
Here is how you would edit your current example to work: http://jsfiddle.net/andytjoslin/ctyfg/21/. But this way ends up being bad, because you have to do DOM manipulation in your controller.
You just need to create a directive that will basically do what you wanted ng-bind-html to do: http://jsfiddle.net/andytjoslin/ctyfg/22/

Resources