angular ng-loop dynamic input and dynamic value to data processing - angularjs

i am trying to create a dynamic form in angular. if type is text, the input will be <input type="text">. If type is checkbox, it will display <input type="checkbox">
here is the data successfully requested from server that i put in controller $scope
.controller('FormCtrl', function($scope){
$scope.form_data = [
{"id":1,"question":"Name","type":"text","user_criteria":"faiz","answer":[]},
{"id":5,"question":"Hair Type","type":"checkbox","user_criteria":"Long","answer":[{"id_answer":10,"id_survey":5,"answer_txt":"Long"},{"id_answer":11,"id_survey":5,"answer_txt":"Short"}]}
];
$scope.updated_form = {};
});
this is the template
<div ng-repeat="fm in form_data">
<div ng-if="fm.type =='text'">
<label>{{fm.question}}</label>
<input type="text" ng-model="{{fm.user_criteria}}">
</div>
<div ng-if="fm.type =='checkbox'">
<div ng-repeat="ans in fm.answer">
<input type="checkbox"> {{ans.answer_txt}}
</div>
</div>
</div>
for the input type text value. it appears label print Name and the input value print faiz. the code are displayed successfully to the correct input type and value.
but i have 2 question.
is there a way in the checkbox to check the value of the user_criteria to check the checkbox input?
how to pass all this data into the $scope.updated_form so i can use the value from the input like this ?
$scope.updated_form = [
{"id":1, "user_criteria": "faiz new name"},
{"id":5, "user_criteria": "Short"}
];
i am stuck to pass the form data for processing since i am lost when it comes to nested loop in the checkbox

I made a small sample to resolve your issues:
http://jsbin.com/pahuwe/3/edit?html,js,output
I used a initial fill function, to transfer the data to updated_form field:
$scope.updated_form = [];
$scope.form_data.forEach(function(item) {
$scope.updated_form.push(item);
});
and I used input radio for select, but with model and value parameters:
<input type="radio" ng-model="fm.user_criteria" ng-value="ans.id_answer"/>
Use a same ng-model to permit select a unique response.

My understanding is, you want to know what user checked and inputted , you can use another model to store the user data.(You need to init the updated_form with ids) And for the checkbox, you need to add a function with ng-change to set the checked answer into related data. It will be like
<div ng-repeat="fm in form_data">
<div ng-if="fm.type =='text'">
<label>{{fm.question}}</label>
<input type="text" ng-model="{{updated_form[fm.id].user_criteria}}">
</div>
<div ng-if="fm.type =='checkbox'">
<div ng-repeat="ans in fm.answer">
<input type="checkbox" ng-model="theChecked" ng-change=" if (theChecked) updated_form[fm.id].user_criteria = ans.answer_txt; "> {{ans.answer_txt}}
</div>
</div>

Related

Angularjs difference between fetched and locally modified data

I fetch data from an API and it gives my something like this:
{id: 1, name: ''}
The field name is ng-model for an input field.
As soon as I write something in the field, the json object I have a reference to, will have name equals to something else than empty.
That's normal behaviour.
However, if Im interested in knowing if name "was" empty when I fetched data, can I do this in a simple way? Without needing to create new variables?
Basically I want to have 2 ng-if elements and only display one of them. But I cannot trust the data in the object because I don't know if the name-field has been changed locally or on the server:
<input type="text" ng-model="ctrl.name" ng-if="ctrl.name === ''" />
<span ng-if="ctrl.name !== ''">{{ctrl.name}}</span>
Use can the $dirty (this docs are about form but it's true for inputs as well) prop of an input in form so the logic will be: show the input if the name is not defined (undefined or an empty string) or when the input is dirty - means the user typed in the input. And the opposite for the span. This way you'll not have to hold another param.
angular.module('app', []).controller('myController', function() {
// comment this line to simulate name was empty
// this.name = 'text from server';
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="myController as ctrl">
<form name="myForm">
<input type="text" name="name" ng-model="ctrl.name"
ng-if="!ctrl.name || myForm.name.$dirty" />
<span ng-if="!!ctrl.name && !myForm.name.$dirty">{{ctrl.name}}</span>
</form>
</div>
</div>

Display multiple Field name in single Textbox

I have multiple set off field name and I want to display all those in single textbox using ng-model. But I am able to display only single field name.
This is my code : <p> {{cts.selectedcontact.location.state + " "cts.selectedcontact.location.postcode}} </p>
<input type="text" ng-model="cts.selectedcontact.location.state"+`"cts.selectedcontact.location.postcode"> <br/>`
try this
angular.module("app",[]).controller("appContr",function($scope)
{
$scope.newmodelName="";
$scope.Sample1="ram";
$scope.Sample2="esh";
$scope.Concstring=function(val1,val2)
{
return val1+val2;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="appContr">
<input type="text" ng-init="newModelName =Concstring(Sample1,Sample2)" ng-model="newModelName">
<br />
</div>
well ng-model shall have only one argument, that will be binded to the field value and it will receive the value of the input field every time it is changed. So you can not use several variables in one ng-model.
But if you would like to show it as a default value, then you can set it in the value argument in html, or just in your js file. like so:
<input type="text" ng-model="modelValue"> <br/>
and in .js file:
$scope.modelValue = $scope.cts.selectedcontact.location.state + $scope.cts.selectedcontact.location.postcode;
You can initialize new variable for text box like as
<div ng-init="newField = cts.selectedcontact.location.state + cts.selectedcontact.location.postcode">
<input type="text" ng-model="newField"> <br/>
</div>

Can ng-model replace Ids?

Is there a way to avoid IDs while creating elements i.e. using ng-model it is easier to validate form fields and other stuff?
<div ng-repeat="x in TestData">
<input type="text" id="nameField-{{$index}}"/>
</div>
The above code will display the number of input boxes equal to the length of the TestData array where every text box will have a unique id "nameField-0", "nameField-1" and so on, using these IDs we can take the textbox values, validate the fields etc.
<div ng-repeat="x in TestData">
<input type="text" ng-model=""/> <!-- what shall be done here to have unique IDs -->
</div>
Although going with IDs is working fine for me but as far as I can understand If I use IDs then that will not be a pure angular way (or IDs cannot be replaced by mg-models), correct me If I am wrong.
You don't need to grab element with id/name/etc. You can use ng-model to bind your values and ng-pattern to validate them.
<div ng-repeat="x in testData">
<ng-form name="tForm">
<input type="text" name="tInput" ng-model="x.name" ng-pattern="/^[A-Z]*$/" />
<span ng-if="tForm.tInput.$error.pattern" style="color:red">Invalid!</span>
</ng-form>
</div>
See this jsbin.
In your controller add this,
$scope.nameField = [];
in ng-reapeat add this,
<div ng-repeat="x in TestData">
<input type="text" ng-model="nameField[$index]"/>
</div>
nameField will be an array with all your values.
<div ng-repeat="x in TestData" ng-init='this["nameField-"+x]'>
<input ng-model='this["nameField-"+x]'/>
</div>
You use ng-init to add new variables to the controller, "this" refer to your scope, and since the scope is an object, since this[bla] == this.bla tou are actually saying, add to my scope a variable name "nameField=" and you add the x value.
after you have created your variable, just use it in the same way in your ng-model.
If you want to show your variable's value in any div/span, just use it via ng-bind:
<div ng-bind='this["nameField-"+x]'></div>

ng-model in ng-repeat - how to send values to server

im using ng-repeat to create dynamic number of textboxs.
<div class="orgevent" ng-repeat="i in getNumber(numOfEvents) track by $index">
<input class="dest" type="text" value="Free text" ng-model="i.freeText">
</div>
i want (on click) to take the values that the user write in the textBox and send it to the server,
how can i do it?
i tried to take it in the JS by ng-model but the value is always "undefined"
You can use ng-model as array and read it on click. Take a look
http://jsfiddle.net/ucskyv67/74/
app.controller("cookieCtrl", function ($scope, $cookies) {
$scope.numbers= [1,2,3,4,5,6];
$scope.userVals=[];
$scope.getVal= function(){
console.log($scope.userVals);
}
});
<div ng-app="cookieApp" ng-controller="cookieCtrl">
<div class="orgevent" ng-repeat="i in numbers track by $index">
<input class="dest" type="text" value="Free text" ng-model="userVals[$index]">
</div>
<button ng-click="getVal()">Read</button>
</div>
one option is to add ng-change to your input and implement a method in your controller to call the server-
<input ng-change="handleChange(i.freeText)" class="dest" type="text" value="Free text" ng-model="i.freeText">

Reference the inputs created with ng-repeat in angular based on the number of variable options

The problem I'm facing, as outlined in the code, is that I can't seem to find out how to bind the second checkboxes (created with ng-repeat) to some model which I would then be able to use further down the code (showing/hiding yet another set of options). Also, I managed to show the additional number of inputs based on the count parameter in the $scope.availableOptions by using the $scope.getItterator function, but now I don't see how would I access the values of these checkboxes? I know I have to somehow use the option "ng-model" but am failing to do so, so any help appreciated.
My code is here, but am showing it here too:
html:
<div ng-controller='MyCtrl'>
Show additional options <input type="checkbox" ng-model="additionalOptions">
<div ng-show="additionalOptions">
<ul>
<li ng-repeat="option in availableOptions">
<label class="checkbox" for="opt_{{option.id}}">
<input type="checkbox" name="opt_{{option.id}}" id="opt_{{option.}}" />
{{option.name}}
<ul ng-show="if the upper checkbox is clicked">
<li>
<input type="text" ng-repeat="i in getItterator(option.count)" ng-model="SOME_VALUE_TO_BE_USED_BELOW"/>
Output the value based on what's entered above in the textboxes (SOME_VALUE_TO_BE_USED_BELOW)
</li>
</ul>
</label>
</li>
</ul>
</div>
</div>
and my js:
function MyCtrl($scope) {
$scope.availableOptions = [{"id":"1","name":"easy","count":"2"},{"id":"2","name":"medium","count":"3"},{"id":"3","name":"hard","count":"2"}];
$scope.getItterator=function(n){
var a = new Array();
for(var i=1; i <= n; i++)
a.push(i);
return a;
};
}
Try ng-model="option.checked":
<input type="checkbox" name="opt_{{option.id}}" id="opt_{{option.}}" ng-model="option.checked"/>
And then you can access this property further below like this:
<ul ng-show="option.checked">
DEMO
If you need to also reference the text box inputs. You create a new property (values) on the option. Like this:
{"id":"1","name":"easy","count":"2",values:[]}
Html:
<div ng-repeat="i in getItterator(option.count)">
<input type="text" ng-model="option.values[$index]"/>
{{option.values[$index]}}
</div>
DEMO
Use this:
<input type="checkbox" name="opt_{{option.id}}" id="opt_{{option.}}" ng-model="option.clicked"/>
{{option.name}}
<ul ng-show="option.clicked">
Basically, you are saying that the top checkbox should store its value in a model for each option option.clicked. And then only showing the information based on the scope item.
Updated Fiddle:
http://jsfiddle.net/CkHhJ/26/
UPDATE:
Here is another updated fiddle to answer your questions second part: http://jsfiddle.net/CkHhJ/27/
The difficulties you were having is likely because you are trying to build dynamic input models. Just bear in mind that you need to use an object for the dynamic values (not a plain string, eg: option.answers[$index].value and not just option.answers[$index]. See: AngularJS: Updating an input with a dynamic ng-model blurs on each key press

Resources