I'm trying to use the Switch component from Zurb's Foundation.
It works great until you put it inside an ng-repeat. Then, all the switches except the last one are broken--they don't display the labels until you click them.
Here's a JSBin documenting the issue. Anyone know what's up?
You need ng-model on your radios. It works fine in your JSBin if you include an ng-model on each radio button.
According to the docs, value is also required.
Edit:
Okay look at this version, I finally got it to work with both ng-model and ng-value, which I've learned is preferable to value. What do you think, does that work for you?
Apparently ng-repeat created a child scope for each iteration. Using $parent seems to be a way around that.
Found I had to use "ng-checked" in the following fashion for it to work as expected within an "ng-repeat". As long as the ng-clicked var is unique per switch, should work as expected. Make the toggle function something that toggles the visible value between true and false.
<div class="switch" ng-click="toggle()">
<input type="radio" ng-checked="!visible">
<label>Off</label>
<input type="radio" ng-checked="visible">
<label>On</label>
<span></span>
</div>
Hope that helps someone.
Related
I'm using text-angular to save html-based content into database and i want to save checkboxes with the checked attribute on them. I've tried to use the input field like below but text-angular doesnt render checkboxes with checked attribute. Is there any way to do this without doing pure css checkboxes?
<input type="checkbox" checked>
EDIT: The code I am using:
<text-angular data-ng-model="example_content" placeholder="Content..."
rows="5">
And inside the textarea of the text-angular directive, I am trying to insert the input from above but it renders without checked attribute
I looked up in text-angular's sanitizer library textAngular-sanitize.js to find out that the checked attribute isn't part of their htmlAttrs attribute map.
Hence, the only option we're left with is to override the sanitizer JS file with the edit. Moreover, you can add other attributes/tags if you want (Do consider vulnerabilities though!)
Here's the working example plunker forked from official text-Angular plunker. Notice the ta-sanitize.js included in plunker which is modified version of their textAngular-sanitize.js
Hope this helps!
You can achieve by using ng-click
<input type='checkbox' ng-click='onsaveValue()' ng-model="saveValue">
I'm working on a radio button list where a user can select from a pre-populated list of problems, or select an "other" radio button and then type in their specific problem.
I can get the pre-populated list of radio buttons to work and set the problem (outputting the scope variable confirms this), but introducing the "other" functionality is stumping me. When I select other, it doesn't seem to bind to the scope variable. I noticed in the dom it's missing an class="ng-scope" that the other radio buttons seem to get from the ng-repeat, but I'm not sure if that's the problem.
<form>
// This part loops through the list of problems and makess radio buttons
<div ng-repeat="problem in selectedType['nature_of_problem']">
<input type="radio" ng-model="$parent.natureOfProblem" ng-value="problem"/>
</div>
// Ideally this part is where the "other" radio is, it's still in the form
<input type="radio" ng-model="natureOfProblem" ng-value="other" ng-checked="">
</form>
Working JSFiddle:
http://jsfiddle.net/HB7LU/3794/
I saw a few issues, among them:
Using ng-value instead of plain old value for "other"
Using a primitive instead of dot notation (if you want your view to reliably write a variable, it needs to be something.yourVariable instead of just plain old yourVariable)
Hope this helps!
function MyCtrl($scope) {
$scope.uiState = {};
$scope.uiState.natureOfProblem = 1;
$scope.selectedType = {};
$scope.selectedType.nature_of_problem = [1,2,3];
}
<div ng-controller="MyCtrl">
<p>Nature of problem is: {{uiState.natureOfProblem}}</p>
<form>
<div ng-repeat="problem in selectedType['nature_of_problem']">
<input type="radio" ng-model="uiState.natureOfProblem" ng-value="problem"/><span ng-bind="problem"></span>
</div>
<input type="radio" ng-model="uiState.natureOfProblem" value="Other" /><span>Other</span>
</form>
</div>
EDIT to answer OP's questions:
I tend to use ng-bind out of habit -- in slower browsers like Firefox, it keeps "{{blah}}" from showing up on the screen as everything loads. Newer versions of Angular also have ng-cloak for this purpose, which I should probably get in the habit of using instead. :) (I also vaguely remember reading that "{{blah}}" can cause issues in IE, but I very possibly made that up.)
The use of dot notation relates to the fact that Angular can't maintain data bindings on brand-new objects. To try to explain it without using terms like "scope" and "inheritance": If you influence an existing object by changing yourObject.anAttribute, the overarching object consistently exists throughout that process and does not drop its binding. But if you have blahVariable that is equal to 8, and you set blahVariable equal to 7, you've basically tossed the old piece of data and created a new piece of data entirely. This new piece does not maintain the binding, so the controller never gets the memo from the view that the value has changed.
Sometimes I find this useful, actually -- you can briefly manipulate a variable in the view for some quick-and-dirty purpose without the controller finding out about it. :)
I have no idea how to pre-populate an ng-model in this circumstance that I have to use ngBind. I tried ng-init, but it's not working.
<h6 ng-show="isOwner" ng-bind="currentMagazine.magazine_name"
contenteditable ng-model="currentMagazine.magazine_name"
ng-change="update()"></h6>
I have a seperate directive that binds contenteditable attributes to ngModelController.
The problem now is whenever I update the model, ng-bind will jump out and refresh the div element, resulting in the cursur going back to the beginning of the text, which makes it impossible for any user to type.
I tried ng-init in a fashion like this:
<div ng-init="magazineName = currentMagazine.magazine_name">
<h6 ng-show="isOwner"
contenteditable ng-model="magazineName"
ng-change="update()"></h6>
</div>
It's not working. If I don't use ng-bind, then no text will show up.
Also I notice it might be related to this problem, when I type with space or delete key, they are escaped into HTML entities...so you get result like this:
Hopefully both of my problems can be solved! Thank you (it's a very frustrating day)!
In your app.js do this:
$scope.magazineName = $scope.currentMagazine.magazine_name;
In your HTML do something like this:
<input
ng-show="isOwner"
contenteditable
ng-change="update()"/>
or
<h6 ng-show="isOwner"
contenteditable
ng-model="currentMagazine.magazine_name"
ng-change="update()">
{{currentMagazine.magazine_name}}
</h6>
... though perhaps not, it's a bit difficult to gauge without seeing it... please make a jsfiddle or plunkr if you'd like to get more eyes on it.
If you're just trying to make some large text that is still editable and bound to the model it may be easier to just style an input for your needs.
Decided to play with contenteditbale since it's chance for me to learn something too... I can't seem to recreate the issue though:
http://jsfiddle.net/VSJQX/
I saw after doing this it wasn't updating the model, found another SO post that resolves that and included the changes here:
http://jsfiddle.net/VSJQX/2/
I have a very simple form where a radio button is required to be selected in order for a form to be valid. The radio buttons are generated by ngRepeat.
As you can see from this fiddle, while the desired behavior is that when the radio button is clicked for the first time, that should validate the form (being the only element), however notice that it takes an additional click (on the same radio button or any other) to validate the form:
http://jsfiddle.net/Xsk5X/3/
What am I missing?
All the other solutions are work-arounds: All you have to do is remove the name attribute, when you use the ng-model attribute you don't need it and they conflict.
Specifying the name causes Angular to get confused because it changes the value once for the angular model and another time for the form element name.
I had this problem because a colleague had copied the radio buttons in the same page and hidden them for temporary reference, so duplicate radio inputs with the same name
Try adding the ng-click attribute to your radio button input.
Credit to Manny D for noting this first. Yes, this is a little hackish, but it works. E.g.,
<input type="radio"
name="groupName"
ng-model="editObject.Property"
ng-value="someValue"
ng-click />
The reason why this is breaking - is because you're setting all radio boxes to be required. As a result, depending on how you write it - angularjs is saying it's invalid because not all have been selected at some point.
The way around this is to do something like the following:
Using checkboxes and required with AngularJS
(check the 1st and 2nd answers). This will resolve your problem.
Seems like an AngularJS 1.0.3 $scope.$apply update problem.
Tested your exact Fiddle in 1.0.2 (check it out yourself) and it works the way you expect it too.
It doesn't seem like there's anything wrong with your code, just that $scope.$apply(or $digest) isn't working as expected on the first select.
A very simple fix is to force the $scope to also update on every select, try changing the following line of code in your form:
<p>Favorite Beatle</p>
change it too:
<p>Favorite Beatle: {{name}}</p>
And you will see how myForm.$invalid is updated even after the first click.
I would try it out with the latest AngularJs version and let us know if that happens there too.
Another solution I can think of it setting the default selected radio, which will cause myForm.$invalid to be false from the beginning. you can do this by adding the following line in your controller code:
$scope.name = "John";
or any default name you want.
Some times the $digest cycle dosen't $apply(fn) because you have two o more instances.
For fix this you need $apply this trick manually, so put this in your directives:
angular.('myApp',[])
.directive('ngRadioExtend', ['$rootScope', function($rootScope){
return {
require: 'ngModel',
restrict: 'A',
link: function(scope, iElm, iAttrs, controller) {
iElm.bind('click', function(){
$rootScope.$$phase || $rootScope.$apply()
});
}
};
}])
and use it as:
<input type="radio" name="input_name" ng-model="some" value="F" ng-required="true" ng-radio-extend>
<input type="radio" name="input_name" ng-model="some" value="M" ng-required="true" ng-radio-extend>
DONE it's the correct way!
The problem of the scope not getting updated still occurs in 1.1.5
A simple work around is to just add
<span ng-show="false"> {{name}} </span>
Fiddle: http://jsfiddle.net/jonyschak/xaQJH/
For IONIC v1,
add name="" to prevent ionic auto-generate attribute name.
Then, I can change the selected item with only one click.
<ion-radio class="label-ticket"
ng-repeat="topic in vm.listTopic track by $index"
ng-value="topic"
ng-model="vm.topicSupport"
name="">
{{ topic.title }}
</ion-radio>
I'm building an AngularJS app and I have ran into an issue. I have been playing with the framework for a while and I have yet to see documentation for something like this or any examples. I'm not sure which path to go down, Directive, Module, or something that I haven't heard of yet...
Problem:
Basically my app allows the user to add objects, we will say spans for this example, that have certain attribute's that are editable: height and an associated label. Rather than every span have its own dedicated input fields for height and label manipulation I would like to use one set of input fields that are able to control all iterations of our span object.
So my approx. working code is something like this:
<span ng-repeat="widget in chart.object">
<label>{{widget.label}}</label>
<span id="obj-js" class="obj" style="height:{{widget.amt}}px"></span>
</span>
<button ng-click="addObject()" class="add">ADD</button>
<input type="text" class="builder-input" ng-model="chart.object[0]['label']"/>
<input type="range" class="slider" ng-model="chart.object[0]['amt']"/>
The above code will let users add new objects, but the UI is obviously hardcoded to the first object in the array.
Desired Functionality:
When a user clicks on an object it updates the value of the input's ng-model to bind to the object clicked. So if "object_2" is clicked the input's ng-model updates to sync with the object_2's value. If the user clicks on "object_4" it updates the input's ng-model, you get the idea. Smart UI, essentially.
I've thought about writing a directive attribute called "sync" that could push the ng-model status to the bound UI. I've though about completely creating a new tag called <object> and construct these in the controller. And I've thought about using ng-click="someFn()" that updates the input fields. All of these are 'possibilities' that have their own pros and cons, but I thought before I either spin out on something or go down the wrong road I would ask the community.
Has anyone done this before (if so, examples)? If not, what would be the cleanest, AngularJS way to perform this? Cheers.
I don't think you need to use a custom directive specifically for this situation - although that may be helpful in your app once your controls are more involved.
Take as look at this possible solution, with a bit of formatting added:
http://jsfiddle.net/tLfYt/
I think the simplest way to solve this requires:
- Store 'selected' index in scope
- Bind ng-click to each repeated span, and use this to update the index.
From there, you can do exactly as you proposed: update the model on your inputs. This way of declarative thinking is something I love about Angular - your application can flow the way you would logically think about the problem.
In your controller:
$scope.selectedObjectIndex = null;
$scope.selectObject = function($index) {
$scope.selectedObjectIndex = $index;
}
In your ng-repeat:
<span ng-repeat="widget in chart.object" ng-click="selectObject($index)">
Your inputs:
<input type="text" class="builder-input" ng-model="chart.object[selectedObjectIndex]['label']"/>
<input type="range" class="slider" ng-model="chart.object[selectedObjectIndex]['amt']"/>