jquery checkbox attr change seems not to work - checkbox

Does anyone have any idea why this code seems not to work?
What am I doing wrong?
JQuery 1.5.1 is used.
JS code:
$('#search_filters #discipline a').click(function(){
var checkbox = $(this).next(':checkbox');
if (checkbox.attr('checked')) {
checkbox.attr("checked", true);
} else {
checkbox.attr("checked", false);
}
$(this).children('img').toggleClass("active");
return false;
});
HTML:
<li>
<a href="#">
<img class="inactive" alt="Football" src="/images/disciplines/e9bc7681813110c/thumb.png">
</a>
<input type="checkbox" name="search_discipline[7]" value="1" class="search_discipline">
</li>

I just ran into this myself. It seems in jQuery 1.5.1 and 1.5.2 setting the checked attribute is a bit buggy. I had better luck with $(':checkbox').val(boolean) (which is even a bit easier).
Update: after some digging, it seems the webkit inspector doesn't actually show the checked attribute in the DOM, but jQuery reads/writes it properly. Very odd. Serves me right for using the nightly webkit builds for dev.

The value of a "checked" attribute should be "checked":
if (checkbox.is(':checked'))
{
checkbox.attr("checked", "checked");
} else {
checkbox.removeAttr("checked");
}

Just two helpful ideas to check the change for attributes:
Write the plain HTML first, without Javascript. Did it work? If so, then write it with JS
If you had modified an html tag recall the attribute itself, so you can check that your code had been executed well. E. g. alert($({your target object}).attr({the attribute which added}));
That's what I do in the most cases.

Some pointers:
$('#search_filters #discipline a') will be selecting all a elements that descend from #discipline that descend from #search_filters. Is this what you indend?
Are you remembering that .next() returns a sibling.
What happens if you remove the href='#'?
Does your click event even fire?

Related

Using contenteditable with ng-model inside ng-repeat?

Here is my issue:
I am using ng-repeat to make a list of spans.
Each span has the contenteditable attribute and ng-model directive.
Everything works as expected (including two-way data binding), until I try to add a new item to the list.
<div ng-repeat="item in list">
<span ng-model="item.text" contenteditable></span>
</div>
<button ng-click="addItemToList"></button>
The methods look like this:
$scope.addItemToList = function () {
$scope.list.push({text: 'dummy text'});
}
or
$scope.addItemToList = function () {
$scope.list.splice(1, 0, {text: 'dummy text'});
}
When adding the new item to the list (push or splice), the DOM updates, but the last item is initialised empty, with no text whatsoever. The last item in the model list also empties out, even if I specifically push an element with text in it.
After a few tests, I've noticed that this only happens if the list's length is bigger after modifying it:
if I try to replace/modify/remove (not add) an element in the list, it works well.
I believe this has to do with the way contenteditable elements initialise in the DOM (I think they initialise empty, and somehow, the model empties out as well).
Has anyone encountered this problem before? If yes, how did you solve it / what workaround have you found?
Based on the angular docs related to ngModelController, it seems that there is not built-in support for two-way data binding with contenteditable elements, seeing as in the plunkr example they wrote their own contenteditable directive. You might be able to use a modified version of that as a workaround.
It looks to be a similar problem as this question and the contenteditable directive there looks similar to the contenteditable directive in the angular docs example.
I also found this directive on github that might accomplish what you are trying to do.
Edit: I did a new version of the plunk I posted in the comment above:
https://plnkr.co/edit/v3elswolP9AgWHDIPwCk
In this version I added a contenteditable directive that appears to be working correctly. It is basically a spin off of how the input[type=text] directive is written in angular, but I took out the places where it handles different types of input (since in this case it will just be text) and the places where it handles events that contenteditable elements don't even fire. I also changed it so that the $viewValue gets updated based on element.html() instead of element.val(). You might be able to use something like this as a workaround
The issue is old but that was the same problem for me today. (angular 1.5). My workaround was to add on blur update option: <td contenteditable data-ng-model="position.value" ng-model-options="{updateOn: 'blur'}"></td> somehow then model stopped getting be empty on initialize. I like using update on blur in many places (solves some performaces issues) so this is good for me, however it's some kind of trick.

Angular UI Bootstrap Datepicker is-open

I've been working on this for a while now, and am not sure where to go from here.
I am using Jade for my templates inside my app, and am trying to use the UI Bootstrap date picker as well. In UI Bootstrap 0.10.x everything was working fine, but in 0.13.3 I can't get the is-open attribute on the datepicker to work properly. Here is the jade template excerpt:
input(type="text", ng-model="item.exp_date", datepicker-popup="{{datepicker.format}}", min-date="{{datepicker.minDate}}", is-open="{{datepicker.opened}}", close-text="{{datepicker.closeText}}").form-control
span.input-group-btn
button(type="button", ng-click="openDatepicker($event)").btn.btn-default
i.glyphicon.glyphicon-calendar
You can see that for several attributes I'm using angular expressions to get preset values (i.e. datepicker-popup="{{datepicker.format}}". However, that expression does not work when I try to do the same thing with is-open. All the others work fine, and if I just put is-open="true" in for the attribute, the datepicker at least shows up on page load. The problem is you can never open it again.
Here's the pertinent controller code:
$scope.datepicker = {
format: 'MM-dd-yyyy',
minDate: new Date(),
closeText: "Close",
showWeeks: false,
yearRange: 50,
opened: false
}
$scope.openDatepicker = function($event) {
$scope.datepicker.opened = true;
}
and the error in the browser that pops up:
Error: [$parse:syntax] Syntax Error: Token '{' invalid key at column 2 of the expression [{{datepicker.opened}}] starting at [{datepicker.opened}}].
http://errors.angularjs.org/1.4.5/$parse/syntax?p0=%7B&p1=invalid%20key&p2=2&p3=%7B%7Bdatepicker.opened%7D%7D&p4=%7Bdatepicker.opened%7D%7D
at REGEX_STRING_REGEXP (http://localhost:3030/vendor/angular/angular.js:68:12)
at Object.AST.throwError (http://localhost:3030/vendor/angular/angular.js:12967:11)
at Object.AST.object (http://localhost:3030/vendor/angular/angular.js:12954:16)
at Object.AST.primary (http://localhost:3030/vendor/angular/angular.js:12862:22)
at Object.AST.unary (http://localhost:3030/vendor/angular/angular.js:12850:19)
at Object.AST.multiplicative (http://localhost:3030/vendor/angular/angular.js:12837:21)
at Object.AST.additive (http://localhost:3030/vendor/angular/angular.js:12828:21)
at Object.AST.relational (http://localhost:3030/vendor/angular/angular.js:12819:21)
at Object.AST.equality (http://localhost:3030/vendor/angular/angular.js:12810:21)
at Object.AST.logicalAND (http://localhost:3030/vendor/angular/angular.js:12802:21) <div ui-view="locations" class="ng-scope">
Like I said, the is-open attribute is the only one having this issue. If you have any suggestions for fixing the issue or a work around I'd love to hear it. Thanks!
Of course right after I posted the question, I figured out the problem. Apparently for that attribute, the {{ }} is unnecessary. All the other attributes need the curly braces, but that one doesn't. It must be because it assumes you will be adding in a variable to toggle the visibility.
Whatever the reason, I figured it out and got it working again. I'll leave this up in case anyone else gets as stuck as I did and can't get it working again.
For the atribute of angularjs (whatever) the {{ }} is not necesary, in this atribute you are in angularjs, and not needed call to angularjs.

Odd issue with ng-show always evaluating to true

I had a bit of code in my view that would only show up when a particular value was true. Lt looked like this:
button type="button" ng-click="attachBarCode('enter')" ng-show="barcodeAllowed.status">Foo</button>
This was working until recently. My controller had some logic where, based on Ajax data, it would set $scope.barcodeAllowed.status to true. All of a sudden though, the button was always showing up. To help debug the issue, I added some additional tests to my view:
first test, <span ng-show="!barcodeAllowed.status">DONT SHOW</span><br/>
second test, <span ng-show="barcodeAllowed.status">DONT SHOW</span><br/>
test -{{barcodeAllowed.status}}-end -{{!barcodeAllowed.status}}- -{{barcodeAllowed | json}}-<br/>
test if <span ng-if="barcodeAllowed.status"> if was true</span><p>
Here is where things got crazy. Both "DONT SHOWS" rendered in my view, even though it seems as if that would be impossible. When I output the values in the third line, I saw false and true, as I expected.
Finally - the ng-if? It worked perfectly! The value did not show up.
I've heard folks mention that ngShow can have scope issues inside a ngif, but my code isn't inside an ngif.
So, you won't believe what it was. I was using a Content Security policy in my app and on a whim, I disabled it. As soon as I did, it began working. I played around a bit and discovered that I needed to add 'unsafe-eval' to the to the script-src area of my CSP in order for Angular to be able to apply the styles.
The Ng-show/Ng-hide directives needs a css-class to show/hide, since it just adds a class to your element when the scope-variable is truthy/falsy.
Ref: https://docs.angularjs.org/api/ng/directive/ngShow

how to go from angular event to jquery selector

I know this is bad design but would like to introduce angular to a current project. I would like sayHello to be able to determine whether the element has the class 'is-a-favorite'
<div ng-click="sayHello(29, $event)" class="is-a-favorite" data-type="location" data-global-id="29" data-make-disappear="false"> </div>
$scope.sayHello=function(global_id,event){
//var selector=???
if(selector.hasClass('is-a-favorite')){
console.log("this is-a-favorite");
}
};
How would (or could) I get a reference to current DOM element to query via hasClass?
thx
The clicked element is available as $event.target, so you could check $($event.target).attr('class') or something similar.
EDIT: actually, what you'd want is to check $($event.target).hasClass('is-a-favorite')

ng-include onload not working anymore in angularjs 1.2.0 rc

I am using angular's ng-include like this :
main html:
<span ng-include="'tpl.html'" ng-controller="TplCtrl" onload="loadMe()"></span>
template tpl.html:
<h2>{{ tplMessage }}</h2>
the controller:
$scope.loadMe = function () {
$scope.tplMessage = 'template';
}
})
this was working fine with angularjs 1.1.5 but not anymore in 1.2.0 rc 3
here is a plunkr :
http://plnkr.co/edit/zYRevS?p=preview
any idea how to make this work with 1.2.0 ?
edit:
i saw this : https://github.com/angular/angular.js/issues/3584#issuecomment-25279350
but can't find the answer to this problem here.
ok i found the answer here : https://github.com/angular/angular.js/issues/3584#issuecomment-25857079
ng-include can't be on the same element as ng-controller. In 1.1.5, it was working
here is a working updated plunker with an html element wrapping the ng-include:
http://plnkr.co/edit/CB8jec?p=preview
It seems to have to do with you mixing 2 things on the same tag - it has both ng-include and ng-controller on it. put your span inside of a new one and move the ng-controller to the outside tag.
They might'of changed the order in which these attributes are processed. In general I think mixing them on the same tag is not a good idea.
Because it's just broken, and there is currently no workaround.
According to the change long:
"previously ngInclude only updated its content, after this change ngInclude will recreate itself every time a new content is included. This ensures that a single rootElement for all the included contents always exists, which makes definition of css styles for animations much easier."
but instead of being improved, it appears to have been broken.
According to the comments here the current implementation is broken.
Other sources will tell you the same.

Resources