Adding event on ng-repeat element - javascript

I am very new to angular :). I would like to add a simple event one form element with a particular value, built by ng-repeat. This is how the HTML looks:
<div class="labels">
<div class="checkbox-element" ng-repeat="suggestName in $ctrl.suggests" ng-click="$ctrl.toggleSelection(suggestName, 'suggestsSelection', this)">
<label>
<input type="checkbox" name="suggestsSelection[]"
class="hidden"
value="{{suggestName}}"
><span></span>{{suggestName}}
</label>
</div>
<div class="optionary hidden">
<br>
<div class="question__text">Any other?</div>
<label><input type="text"
ng-model="$ctrl.survey.suggest_other"
name="suggests_other1"></label><br>
</div>
</div>
And the controller code:
vm.survey = {};
vm.suggests = ['quality', 'price', 'habbit', 'other'];
// selected
vm.survey.suggestsSelection = [];
// toggle selection for a given names
vm.toggleSelection = function toggleSelection(value, array, scope) {
var idx = vm.survey[array].indexOf(value);
// is currently selected
if (idx > -1) {
vm.survey[array].splice(idx, 1);
}
// is newly selected
else {
vm.survey[array].push(value);
}
};
What I need is to create an event that would toggle the class "hidden" from the div with class "optionary" after clicking on the last created checkbox ("other" in this case). Clicking on other checkboxes shouldn't affect the "optionary" div.
I tried with some configurations like:
if(scope.$last){
$(scope).closest('.optionary').toggleClass('hidden');
}
or similar. I don;t know what should be the way to approach the topic.

You need to use ng-show and a control variable. Take a look.
jsFiddle here: https://jsfiddle.net/U3pVM/24834/
<div ng-app class="labels" ng-controller="MyCtrl">
<div class="checkbox-element" ng-repeat="suggestName in suggests" ng-click="toggleSelection(suggestName, suggestsSelection, this)">
<label>
<input type="checkbox" ng-model="cbSuggest[$index]" name="suggestsSelection[]" class="hidden" value="{{suggestName}}">
<span>{{suggestName}}</span>
</label>
</div>
<div class="optionary hidden" ng-show="showOther">
<br>
<div class="question__text">Any other?</div>
<label><input type="text" ng-model="survey.suggest_other" name="suggests_other1"></label><br>
</div>
</div>
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.survey = {};
$scope.suggests = ['quality', 'price', 'habbit', 'other'];
$scope.cbSuggest = [];
$scope.showOther = true;
// selected
$scope.survey.suggestsSelection = [];
// toggle selection for a given names
$scope.toggleSelection = function(value, array, scope) {
var showOther = true;
angular.forEach($scope.cbSuggest, function(k,v){
if(k) {
showOther = false;
}
});
$scope.showOther = showOther;
};
}

As you can see ng-repeat has special properties: https://docs.angularjs.org/api/ng/directive/ngRepeat
The one you're interested in is $last. You could add ng-change to your checkboxes, call a function with the paramter $last, and that function would set a scope variable. The hidden class could rely on that.
Something like this:
<input type="checkbox" name="suggestsSelection[]"
class="hidden"
ng-change="showHidden($last)"
value="{{suggestName}}">
And in your controller:
$scope.hidden = true;
$scope.showHidden = function(isLast) {
if (isLast) $scope.hidden = false;
else $scope.hidden = true;
}
And then you add ng-class to your div:
<div class="optionary" ng-class="{'hidden': hidden}">...</div>

Related

Modify input names in childnodes with JavaScript

I need help extending this JavaScript (borrowed from https://www.quirksmode.org/dom/domform.html):
var appCounter = 0;
function anotherApp() {
appCounter = appCounter + 1;
var newAppField = document.getElementById("keyApp").cloneNode(true);
newAppField.id = '';
newAppField.style.display = 'block';
var newApp = newAppField.childNodes;
for (var i = 0; i < newApp.length; i++) {
var theName = newApp[i].name
if (theName) {
newApp[i].name = theName + appCounter;
}
}
var insertApp = document.getElementById('keyApp');
insertApp.parentNode.insertBefore(newAppField, insertApp);
document.getElementById('appCount').value = appCounter
}
This works fine when element in my form is:
<div id="keyApp" style="display:none">
<input type="text" name="application" id="application">
<input type="text" name="usage" id="usage">
<\div>
But when I add div's around the inputs (bootstrap styling reasons) I loose the ability to update the input names:
<div id="keyApp" style="display:none">
<div class="col-md-2">
<input type="text" name="application" id="application">
</div>
<div class="col-md-2">
<input type="text" name="usage" id="usage">
</div>
<\div>
How do I extend the script to modify the input names in these new div's?
Since there is now another layer, you need to get newApp[i].childNodes[0] now in order to get the actual input elements.
newApp now holds a list of the div elements with col-md-2 styling, and you need to get the children inside of these div elements.

angular ng-disable checkbox not update with dynamic source

I have several checkboxes dynamicaly generated from array source:
/*js*/
$scope.arrondissements = JSON.parse('
[{"name":"4e","checked":false,"disable":true},
{"name":"5e","checked":false,"disable":false},
{"name":"11e","checked":false,"disable":false},
{"name":"12e","checked":false,"disable":false},
{"name":"13e","checked":false,"disable":false},
{"name":"14e","checked":false,"disable":false},
{"name":"15e","checked":false,"disable":false},
{"name":"16e","checked":false,"disable":false},
{"name":"17e","checked":false,"disable":false},
{"name":"18e","checked":false,"disable":false},
{"name":"19e","checked":false,"disable":false},
{"name":"20e","checked":false,"disable":false}]');
<!-- HTML -->
<div ng-repeat="item in arrondissements" class="checkbox-inline ">
<label>
<input type="checkbox" ng-disabled="{{item.disable == true}}"
value="{{item.checked}}" ng-model="item.checked" >
<span>{{item.name}}</span>
</label>
</div>
Checkboxes are generated correctly but When source gets updated , checkbox doesn't update
/*js*/
$scope.disableCb = function () {
$scope.arrondissements[5].disable = true;
$scope.arrondissements[6].disable = true;
$scope.arrondissements[7].disable = true;
}
<!-- HTML -->
<button ng-click="disableCb()">disable</button>
Could you tell me why and how to fix it?
I made a Plunker : http://plnkr.co/edit/jD1l3NgJuduTOoskpeVM
You should define your $scope.disableCb function inside your controller function.
function controller( $scope) {
var vm = $scope;
$scope.title = 'controller';
$scope.arrondissements = JSON.parse('[{"name":"4e","checked":true,"disable":true},{"name":"5e","checked":false,"disable":false},{"name":"11e","checked":false,"disable":false},{"name":"12e","checked":false,"disable":false},{"name":"13e","checked":false,"disable":false},{"name":"14e","checked":false,"disable":false},{"name":"15e","checked":false,"disable":false},{"name":"16e","checked":false,"disable":false},{"name":"17e","checked":false,"disable":false},{"name":"18e","checked":false,"disable":false},{"name":"19e","checked":false,"disable":false},{"name":"20e","checked":false,"disable":false}]');
$scope.disableCb = function () {
$scope.arrondissements[5].disable = true;
$scope.arrondissements[6].disable = true;
$scope.arrondissements[7].disable = true;
}
}
I've also fixed how you used your directives. I've removed the value attribute on the checkboxes since they're redundant with ng-model.
I've fixed your usage of ng-disabled as well
<div ng-repeat="item in arrondissements" class="checkbox-inline ">
<label>
<input type="checkbox" ng-disabled="item.disable"
ng-model="item.checked" >
<span>{{item.name}}</span>
</label>
</div>
<button ng-click="disableCb()">disable</button>
see my fork on your plunker: http://plnkr.co/edit/v1fwlf7QH0189WAhv6qM?p=preview

How to add new field when button is clicked multiple times by using angularjs

I'm trying to add fields multiple times up on clicking the buttons , they r nested each other..what i am trying to do as shown in the picture
html code :
<body ng-controller="myController">
<form name="{{form.name}}" ng-repeat="form in forms">
<div ng-repeat="cont in form.contacts">
<select>
<option>--select machine--</option>
<option>data1</option>
<option>data2</option>
</select>
<div class="data">
<button class="add_s" ng-click = "add()">Add more</button>
</div>
</div>
<button ng-click="addFields(form)">Add</button>
</body>
angularjs code:
var app = angular.module('myApp', []);
app.controller('myController', function($scope) {
$scope.forms = [{ }];
$scope.addFields = function (form) {
if(typeof form.contacts === 'undefined') {
form.contacts = [];
}
form.contacts.push('');
}
$scope.add = function(){
var max_fields = 10; //maximum input boxes allowed
var wrapper = $(".data"); //Fields wrapper
var add_button = $(".add_s"); //Add button ID
var y=1;
var x = 1;//initlal text box count
$(add_button).click(function(e){ //on add input button click
e.preventDefault();
if(x < max_fields){ //max input box allowed
x++; //text box increment
$(wrapper).prepend('<div><select><option>--select--</option><option>data1.1</option><option>data1.2</option></select><input type="text"><input type="text"><input type="text"><input type="text"><i class="glyphicon glyphicon-trash"></i></div>');
}
});
$(wrapper).on("click",".remove_field", function(e){ //user click on remove text
e.preventDefault(); $(this).parent('div').remove(); x--;
})
}
});
error:
if i click on add button i m getting only one time the above div tag is repeating, but i want that should repeat for many times,
and when i am clicking add more button data with in the 2nd div tag should repeat. but its happening..:( ..
please help.. thank u in advance.
Use this code. Here is the plunker.
$scope.forms = [];
$scope.addForms = function () {
$scope.forms.push({contacts : []});
};
$scope.addContact = function (form) {
form.contacts.push({});
};
View
<form name="{{form.name}}" ng-repeat="form in forms" style="border:1px solid red">
New Form
<div ng-repeat="cont in form.contacts">
<select>
<option>--select machine--</option>
<option>data1</option>
<option>data2</option>
</select>
</div>
<div class="data"> <!-- Move this out of contacts -->
<button class="add_s" ng-click = "addContact(form)">Add more</button>
</div>
</form><!--You have unclosed form tag -->
<button ng-click="addForms()">Add</button>
Here's my take on your problem and how I'd do it :
<div ng-controller="MyCtrl">
<button ng-click="addBloc()">
Add bloc
</button>
<div ng-repeat="bloc in blocs">
<div>
<button ng-click="addNewField($index)">
Add field
</button>
</div>
<div ng-repeat="field in bloc.fields">
<select ng-model="field.gender">
<option value="Male">Male</option>
<option value="Female">Female</option>
</select>
<input type="text" ng-model="field.FirstName">
<input type="text" ng-model="field.LastName"> {{field.gender}} {{field.FirstName}} {{field.LastName}}
</div>
</div>
</div>
And controller :
$scope.blocs = [];
$scope.fields = [];
$scope.addNewField = function(index) {
alert(index);
$scope.blocs[index].fields.push({
gender: "",
FirstName: "",
LastName: ""
});
};
$scope.addBloc = function() {
$scope.blocs.push({
fields: []
});
Working JSFiddle : JSFIDDLE
Basic idea is to put your fields inside a ng-repeat and bind it to an empty array. When you click the button it adds an empty element inside the array which will be binded to a new element of the ng-repeat automatically.
Happy coding!
EDIT : I added another level of repeated fields as previously asked since I forgot to read the entire request.

how to use ng-show with checkboxes

I have tried all the solutions i could find but i am stuck. I have 2 checkboxes, HBO and Marvin. Marvin needs to show a div. HBO needs to show nothing. It works until I need to click the checkbox twice for it to show/hide. usually this would be a $apply() issue but that does not seem to be the case. I believe I am not updating the model correctly. I forgot to mention that the checkboxes need to reset to false when the other is true.
plunker
var ctrl = this;
ctrl.showMeMarvin = function () {
if (ctrl.show === true) {
//$timeout(function () {
ctrl.marvin = false;
ctrl.show = false;
ctrl.hbo = false;
//})
}
else {
//$timeout(function () {
ctrl.marvin = true;
ctrl.show = true;
ctrl.hbo = false;
//})
}
};
ctrl.showMeHBO = function () {
if (ctrl.show === true) {
// $timeout(function () {
ctrl.show = false;
ctrl.hbo = true;
ctrl.marvin = false;
//})
}
else {
//$timeout(function () {
ctrl.marvin = false;
ctrl.hbo = true;
//})
}
};
Just change the div ng-show like this:
<div class="col-xs-12" ng-show="checkedHBO == 1">
And it will work without any additional functions calls.
Edit:
To have it working with the condition to reset the prev selected value you can use this:
<div ng-controller="ShowController as ctrl">
<div class="col-xs-12">
<label for="checkedHBO" class="ts-label">HBO</label>
<input id="checkedHBO" name="mygroup" type="radio" value="hbo" ng-model="checkedHBO" ng-change="checkedMarvin = undefined"/>
<label for="checkedMarvin" class="ts-label">Marvin</label>
<input id="checkedMarvin" name="mygroup" type="radio" value="marvin" ng-model="checkedMarvin" ng-change="checkedHBO = undefined"/>
</div>
<div class="col-xs-12" ng-show="checkedHBO">
<center>
<div class="jumbotron">
DIV 1
</div>
<div class="jumbotron">
DIV 2
</div>
<div class="jumbotron">
DIV 3
</div>
</center>
</div>
</div>
You should be using a radio input instead of checkboxes. http://plnkr.co/edit/hE68w9RKUoFamAWGgRzR?p=preview
<input name="radio" id="checkedHBO" type="radio" ng-model="ctrl.show" ng-value="false" />
<input name="radio" id="checkedMarvin" type="radio" ng-model="ctrl.show" ng-value="true"/>

angular show inputs base checkbox ng-model make inputs unreachable

Please help, I have the following code
<div>
<input type="checkbox" id="chk1" ng-model="Status" />
<span ng-bind="Title"></span>
</div>
<div id="div1" ng-show="Status">
<span ng-bind="SpanTitle" ></span>
<input type="text" id="txtLastName"
ng-model="LastName"
ng-click="LastNameClick()"
ng-blur="LastNameOut()"
name="txtLastName" />
</div>
and when checkbox is being checked the div1 is shown but the input text cannot be clicked or written.
Any idea please?
Edit: Added controller from user's comment
function DController($scope) {
var defaultInputText = "hello";
$scope.Title = "check";
$scope.SpanTitle = "Span";
$scope.Status = false;
$scope.LastName = defaultInputText;
$scope.LastNameClick = function () {
if ($scope.LastName ==defaultInputText) {
$scope.LastName = "";
}
}
$scope.LastNameOut = function () {
if ($scope.LastName.length == 0) {
$scope.LastName = defaultInputText;
}
}
}
From code, that you have provided, I can suggest, that problem can be in css. May be some elements overlap the input.

Categories