All of the examples I have found show the radio button group being built by some for item in items loop but none of them show a simple accessing of the radio button group array in the angularjs controller. What I need to do is traverse through the button group array to see if any of them are in "selected" state.
var radioSelected = false;
for(var i =0; i < items.length; i++) {
if(items[i].selected) {
radioSelected = true;
}
}
I have tried binding to the ng-model and accessing it .. I have tried using $scope.ButtonGroupName Nothing yeilds an array that I can traverse with a loop. Any suggestions on how to do this once VERY simple activity would be greatly appreciated.
Gotta love being forced to relearn web development because somebody broke out a new shiney hammer.
You would not traverse the DOM elements. You would use the same ng-model for all the radio elements, and that would be updated whenever you change the selected state of the radio button.
<input type="radio" ng-model="assignedValue" name="myRadio" value="one">
<input type="radio" ng-model="assignedValue" name="myRadio" value="two">
<input type="radio" ng-model="assignedValue" name="myRadio" value="three">
You would $watch the $scope.assignedValue for changes instead of traversing the DOM elements.
$scope.$watch('assignedValue', function (newValue, oldValue) {
..do stuff here
});
See here for documentation: https://docs.angularjs.org/api/ng/input/input%5Bradio%5D
The reason you don't traverse the DOM is because it's constantly changing. The whole point of Angular is to work off of data and not the elements themselves.
Update: Based on your comments, it sounds like only want to execute an action if a radio button has been selected.
First, a radio button should always have a selected state. Let's pretend it doesn't though. You can enable / disable / show / hide elements in angular in a couple of ways without writing additional DOM manipulation code.
Taking the example above, this button will only be enabled if the assignedValue is two.
<button ng-disabled="assignedValue != 'two'">My button</button>
You can also conditionally include content using ng-if:
<div ng-if="assignedValue == 'two'>
My conditional content
</div>
This will also work with ng-switch
<div ng-switch on="assignedValue">
<div ng-switch-when="two">My additional content</div>
<div ng-switch-default>Here's switch fallback content</div>
</div>
Related
I'm new to Angular JS and i'm trying to create a small web app for learning.. I am trying to make a Tooltip text on mouseover but i'm not sure how to get it done the "Angular way"..
I created 2 spans, when hovering the first, i want to show the second
I tried using ng-mouseover and ng-mouseleave to call the actions-
<span class="info" ng-mouseover="info_in();" ng-mouseleave="info_out();">
<img src="images/info.png" />
</span>
<span class="info_bubble" ng-show="info">The Tooltip Text</span>
And that's where i got with the JS-
$scope.info_in = function() {
this.parent().find('.info_bubble') = true;
};
$scope.info_out = function() {
this.parent().find('.info_bubble') = false;
};
There are going to be more than 1 Tooltip text on each page and i'm not sure how to get it done.. I tried with "next()" and "closest()" but couldn't get it to work
When i try to mouseover the element, i get "this is not a function"
You've got the right idea but your implementation is moving toward the jQuery way, not the Angular way. :)
Try this:
<span class="info" ng-mouseover="info=true" ng-mouseleave="info=false">
<img src="images/info.png" />
</span>
<span class="info_bubble" ng-show="info">The Tooltip Text</span>
No controller code is necessary for this to work.
What you're doing is that when the mouse enters the image, Angular will set $scope.info to true. And since your tooltip is watching that scope variable, it will trigger the ng-show directive to fire which will show your tooltip.
The ng-show directive can be translated as: When $scope.info == true, then show() this element. When $scope.info == false, then hide() this element.
In fact, you could be more verbose (which is good for learning) writing your tooltip element like this:
<span class="info_bubble" ng-show="info==true">The Tooltip Text</span>
I notice that you're using the jQuery method of specifically trying to find an element in the DOM in order to work with it.
The Angular way is to change variables on the $scope. Other HTML elements will monitor variables on the $scope and will automatically change themselves depending on what the new value is. The jQuery way is to reach out and specifically touch and set a value on a DOM element. The Angular way is akin to shouting to the wind, "Hey, my name is $scope.info and I'm now true!" and expecting that some other element will hear it and go, "Ok cool, now I can show myself because $scope.info is true."
That's the main difference between the way jQuery and Angular work.
I'm very very new to Angular JS and have the following requirement:
I have an ng-repeat as shown below:
<div class="panel" ng-repeat="(appname, value) in chart.accordionData" style="margin-top: 0;">
<div class="accordion collapsed" data-parent="#accordion1"
data-toggle="collapse"
data-target="#{{appname.replace(' ','')}}">
<div class="accordion-head" initial-select index="{{$index}}">
<div class="arrow chevron"></div>
<h4><i></i>{{appname}}</h4>
</div>
</div>
<div class="accordion-body collapse" id="{{appname.replace(' ','')}}">
<p class="highlightable" >
Some data
</p>
</div>
</div>
The data in this ng-repeat comes from the server.
So the problem statement I have is to perform a click trigger on the first element under ng-repeat, .accordion-head so that the first item in the list is always open. I tried various approaches of putting $watch etc. but when the number of items in the list are same, then the trigger doesn't fire.
(the first item in list has to be clicked even when new data is loaded)
I thought of writing a directive initial-select and perform click based on index but that happens only once. I really need an experts advice.
Any solutions?
I think the simplest option is to use data-ng-init="collapse = !$first;".
Another option:
Have you used Angular UI Bootstrap? Also, are you using $http or $resource to get data from the server?
If you use $resource, you can set a variable on the success callback (interceptor response) to open=true. Then, you can either bind this variable to Angular UI Bootstrap is-open attribute or to your data-toggle. Also, with $resource you can set data-ng-if="chart.accordionData.$resolved" (or chart.$resolved depending on your setup), which is nice.
You can use a watch to watch the array contents.
Check out the following fiddle:
http://jsfiddle.net/akonchady/w0qdsen7/3/
I have used a variable to keep track when the array content changes since directly watching the array will be more memory intensive.
Here is the main code that watches the variable:
$scope.$watch('arrModified', function(newValue, oldValue) {
if(newValue) { //array is modified
//Trigger ng-repeat div click
setTimeout(function() {
$('.item:first').trigger('click');
$scope.arrModified = false;
$scope.$digest();
}, 0);
}
});
I'm trying to make a check box that should be ticked when a value from the controller is filled (!= null).
It also need to be able to be ticked off and on, but I can't get it to work:
<input type='checkbox'
ng-false-value="''"
ng-model="entry[element.propertyName]"
id="q{{element.id}}"
ng-checked="entry[element.propertyName] != ''"
>
The check box is ticked when entry[element.propertyName] is filled, so far so good. But when I untick the check box the model remains unchanged, even though I've set ng-false-value, and the 'selected=selected' attribute doesn't disappear. When I tick and untick again, then the model starts to change to true and ''
Should be the easiest thing in the world, what am I missing here?
I'm using Angular 1.3.11
I have no idea why you are using ng-false-value, never saw that before.
Here is a snippet with a button updating a checkbox.
function testCtrl($scope){
// Initialise the checkbox as unckecked
$scope.testIsChecked=false;
// This function makes the checkob checked
$scope.makeItCHecked = function(){
$scope.testIsChecked=true;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
<div ng-controller="testCtrl">
<div><input type="checkbox" ng-model="testIsChecked">
$scope.testIsChecked value : {{testIsChecked}}</div>
<button ng-click="testIsChecked=true">Make it checked</button>
</div>
</div>
See this link for explanation.
You can include the array in an object like:
public class objElement
{
string[] propertyName;
}
and then bind to your checkbox.
I am working on a website that displays numerous articles. Each article has a comment section. I have effectively been able to recursively write the comments to the DOM with recursion inside an ng-repeat. However, I need to be able to click on a respond button on any of the comments (they display in a nested fashion) and for a div to be inserted beneath the clicked button. This div would contain a text area for the comment they want to submit and a button. When this second button is clicked, the controller will save the comment to the database. I initially wanted to do this by directly manipulating the DOM from the controller. However, after further research, that would be in direct violation of the MVC/MVW pattern. I believe the correct answer is to create a custom directive. Please give me some insight on how to correctly do this. Any and all information would be very helpful. Thanks in advance.
If you want to add response div dinamically:
<div ng-repeat="article in articles" id="article-{{$index}}">
<p>{{article.content}}</p>
<button ng-click="addAnswer($index)">Add Answer</button>
</div>
js:
myApp.controller("articlesController", function($compile){
$scope.addAnswer = function (index) {
var div = $("<div></div>");
var input = $("<input type='text' ng-model='article.response'></input>");
div.append(input);
var button = $("<button>Send</button>");
button.attr("ng-click", "sendResponse(article)");
$compile(div)($scope);
$("#article-" + index).append(div);
};
});
You don't really need to make a directive to achieve this.
html:
<div ng-repeat="article in articles">
<p>{{article.content}}</p>
<input type="text" ng-model="article.response"></input>
<button ng-click="sendResponse(article)">Send</button>
</div>
js:
myApp.controller("articlesController", function($http){
$scope.sendResponse = function (article) {
console.log(article.response);
$http.post(url, article);
};
});
Of course, you can do it better by hidding input and send button, and show it after user clicks over an answer button.
I'm trying to add some text to the last cursor place after clicking a button.
In the controller:
$scope.addEmoji = function(name){
var element = $("#chat-msg-input-field");
element.focus(); //ie
var selection = element.getSelection();
var textBefore = $scope.chatMsg.substr(0, selection.start);
var textAfter = $scope.chatMsg.substr(selection.end);
$scope.chatMsg = textBefore + name + textAfter;
}
$scope.updateChatMsg = function(chatMsg){
$scope.chatMsg = chatMsg;
}
$scope.sendChatMsg = function(){
var backend = $scope.convs[$scope.active.conv].backend.name;
$scope.view.addChatMsg($scope.active.conv, $scope.active.user, $scope.chatMsg,new Date().getTime() / 1000, backend);
Chat[backend].on.sendChatMsg($scope.active.conv, $scope.chatMsg);
$scope.chatMsg = '';
};
And then some HTML:
<div class="chat-msg-button" >
<button ng-click="view.toggle('emojiContainer')" ><img src="/apps/chat/img/emoji/smile.png"></button>
</div>
<form id="chat-msg-form" ng-submit="sendChatMsg()">
<div class="chat-msg-button" >
<button type="submit"><div class="icon-play"> </div></button>
</div>
<div id="chat-msg-input">
<textarea id="chat-msg-input-field" autocomplete="off" type="text" ng-model="chatMsg" ng-change="updateChatMsg(chatMsg)" placeholder="Chat message"></textarea>
<div>{{ chatMsg }}</div>
</div>
</form>
What I'm trying to achieve: a user types some text in the textarea => $scope.chatMsg gets the value of the textarea. Now the user press one of the button's => the name of the button is added to the latest cursor position. (it's no problem to find the latest cursor position)
The problem
There is a difference between the value of $scope.chatMsg, {{ chatMsg }} inside the div and the text in the textarea.
The contents of the textarea and the div stays always the same. But when pressing the button the name is added to $scope.chatMsg but the contents of the textarea isn't changed...
How can I solve this?
TIA
First of all, you're mixing jQuery with AngularJS, it doesn't look like you need jQuery here that much.
Also, your chat message is updated in 3 different functions, so you need some debugging to see which are fired.
In general:
To solve your issue, try some more debugging, do a
$scope.$watch($scope.chatMsg, function(){
console.log($scope.chatMsg);
});
this will watch all changes to chatMsg. Add console.log() to each of your functions and you can watch which is fired.
Also, rather than using {{ }} inside your div just use ng-bind since that text is the only item in your div, it's cleaner if your app crashes somewhere.
// change from
<div>{{ chatMsg }}</div>
// to
<div ng-bind="chatMsg "></div>
Update: after seeing your plunker, I modified it and came up with this: http://plnkr.co/edit/oNKGxRrcweiJafKCm9A5?p=preview
Your ng-repeat needs to be tracked by $index so that duplicates are displayed rather than crashing when someone creates the same message
I solved all problems. The plunkr form above works. So after investigating all scopes with the Angular chrome extension I saw that chatMsg was defined in another scope. Thus not in the scope I was trying to acces it from.
Via this question angularJS ng-model input type number to rootScope not updating I found a solution.
I added chatMsg to the fields object.