angularjs: ng-model double object - javascript

I try to achieve a double nested object. (Example Below)
The Problem is that my current Code is generating a Array inside a Object.
<div ng-if="newResultUnits()" ng-repeat="set in sets" ng-model="newexercise.sets[$index]">
<label>Set {{$index+1}}</label>
<label>
<label>
<input type="text" ng-repeat="resultUnit in newResultUnits()" ng-model="newexercise.sets[$parent.$index][$index].value" placeholder="{{resultUnit.name}}">
</label>
</label>
</div>
Example (the name attr is added later):
{
name:"MultiTest",
sets:[
{
0:{
value:"10",
name:"Kg"
},
1:{
value:"10",
name:"Wdh"
}
}
]
}
This is how it should be: (Please note the doubble [[ and the missing 0:)
{
"name": "MultiTest",
"sets": [
[
{
"value": "10",
"name": "Kg"
},
{
"value": "10",
"name": "Wdh"
}
]
]
}
Im sorry if I mixedup Array and Object.. Thanks!

You need properly initialize your data structures. So in controller begin with
$scope.newexercise = { sets: [] };
So Angular knows that you want $scope.newexercise to be an array. Then in template use ngInit on every inner loop ng-init="newexercise.sets[$parent.$index] = []":
<div ng-repeat="set in sets">
<label>Set {{$index+1}}</label>
<label>
<label>
<input type="text"
ng-repeat="resultUnit in newResultUnits()"
ng-init="newexercise.sets[$parent.$index] = []"
ng-model="newexercise.sets[$parent.$index][$index].value"
placeholder="{{resultUnit.name}}">
</label>
</label>
</div>
Demo: http://plnkr.co/edit/s1rInT8rLg50ISsSVxyV?p=preview

Related

Angular reactive form *ngFor loop, cannot read 'property' of undefined

StackBlitz example
I'm trying to loop dynamic values to create radio button items on my form. I have managed to display the three radio buttons coming from my data:
radiot: [
{
section: "yes",
sectionCode: "1"
},
{
section: "no",
sectionCode: "2"
},
{
section: "maybe",
sectionCode: "3"
}
]
The problem is I cant display the option of "section".
e.g.
<div class="form-check-inline" *ngFor="let item of personal.radioButtons.radiot; let i = index">
<label for="yes" class="col-12 customradio"
><span>{{item[i].section}}</span>
<input value="{{item[i].section}}" id="{{item[i]}}" type="radio" [formControlName]="i"/>
<span class="checkmark"></span>
</label>
</div>
What am I doing wrong? getting the error - Cannot read property 'section' of undefined
StackBlitz example
You don't need to use i in *ngFor you already have reference to the object at that position.
So for the first iteration your item would be
{
section: "yes",
sectionCode: "1"
}
So you can just do item.section - no need for the index position.
<span>{{item.section}}</span>
Change your template from [formControlName] to formControlName
<label for="{{item.section}}" class="col-12 customradio"
><span>{{item.section}}</span>
<input value="{{item.section}}" name="formGroupName" id="{{item.section}}" type="radio" formControlName="radiot"/>
<span class="checkmark"></span>
</label>
As it is currently written you were telling angular to look for a variable named radiot which is undefined, but what it needs is a string so it can look for it as a property on the current form object
You should put = instead of :
radiot = [
{
section: "yes",
sectionCode: "1"
},
{
section: "no",
sectionCode: "2"
},
{
section: "maybe",
sectionCode: "3"
}
];

angularjs filter with an "OR" operation on data when we have multiple filters

I checked other question but they don't seem to solve my issue.
Here is my code :
var app = angular.module('myApp', []);
app.controller('listdata', function($scope, $http) {
$scope.users = [{
"name": "pravin",
"queue": [{
"number": "456",
"status": "Unavailable"
},
{
"number": "111",
"status": "Unavailable"
}],
"phone": "7411173737"
},
{
"name": "pratik",
"queue": [{
"number": "111",
"status": "Unavailable"
}],
"phone": "8558855858"
},
{
"name": "priyanka",
"queue": [{
"number": "456",
"status": "Unavailable"
}],
"phone": "5454573737"
},
{
"name": "prerana",
"queue": [{
"number": "111",
"status": "Unavailable"
}],
"phone": "7454543737"
}];
$scope.filter111 = function (user) {
return (user.queue.find(({number}) => number === '111'));
}
$scope.filter456 = function (user) {
return (user.queue.find(({number}) => number === '456'));
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.0/angular.min.js"></script>
<div ng-app="myApp">
<label class="switch">
<input type="checkbox" ng-model="queue111">111
</label>
<label class="switch">
<input type="checkbox" ng-model="queue456">456
</label>
<div class="row" ng-controller="listdata">
<div ng-repeat="user in users|filter: queue111? filter111: ''|filter: queue456? filter456: ''">
<p> {{user.name}} {{user.phone}}</p>
</div>
</div>
</div>
I have created custom functions $scope.filter111 and $scope.filter456 respectively to filter data
Currently when I click the checkbox 111, the filter return only the record whose queue has a number 111 and when I click the checkbox 456, the filter returns only the records whose queue has a number 456. This much is working perfectly. When I click both the filters it displays only that object whose queue has both the number 111 and 456 i.e an AND operation is occurring here.
Expected result : I want it such that when I click both the checkbox
it should display all the records from 111 as well as 456 together i.e an OR operation.
How do I do this?
You can try creating a custom angularJS filter by referring w3schools.com example and this link (for better understanding of custom filters).
In your case, the custom angularjs filter would take 3 inputs, i.e the list you want to filter and the value of the checkboxes- queue111 and queue456. Perform filtering and returning the data by providing necessary conditions based on the value of checkboxes inside the filter.
This also reduces the code that you use in your HTML for filtering inside ng-repeat from
<div ng-repeat="user in users|filter: queue111? filter111: ''|filter: queue456? filter456: ''">
<p> {{user.name}} {{user.phone}}</p>
</div>
to
<div ng-repeat="user in users|customFilter: queue111:queue456">
<p> {{user.name}} {{user.phone}}</p>
</div>
where
customFilter is the name (can be any name, provided that name as
an example) of the angularJS filter you create.
users will be the default first input of your custom filter and the value of your checkboxes will be the 2nd and 3rd input respectively.
Also, it would be helpful if you provide codepen/plunker demos so that people can debug your problem and provide solutions easily.

ngOptions with dynamic option array from index

I am trying to use ngRepeat. Within that, I have a select element whos options vary depending on another select. I currently am calling vm.getOperators(filter.keyIndex) in the ng-options, but I get and indefinite loop error from angular. How can I have the following "filterOperator" select options depend on filterColumn select value within an ngRepeat?
html:
<div class="form-group row" ng-repeat="filter in vm.filters">
<div class="col-sm-4">
<select class="form-control" name="filterColumn" ng-model="filter.keyIndex">
<option ng-repeat="key in vm.filterOptions.keys"
value="{{ $index }}">
{{ key.column }}
</option>
</select>
</div>
<div class="col-sm-2">
<select class="form-control" name="filterOperator" ng-model="filter.operator" ng-options="key as value for (key, value) in vm.getOperators(filter.keyIndex)"></select>
</div>
<div class="col-sm-4" ng-model="filter.value">
<input type="text" class="form-control"/>
</div>
<div class="col-sm-1" ng-show="$last" ng-click="removeFilter($index)">
<button type="button" class="btn btn-primary"><span class="glyphicon glyphicon-plus"></span></button>
</div>
<div class="col-sm-1" ng-show="vm.filters.length > 1" ng-click="addFilter()">
<button type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span></button>
</div>
</div>
controller.js:
app.controller('searchCtrl', function() {
var defaultFilter = {
keyIndex: "0",
operator: "",
value: "",
};
var operatorMap = {
"0": "=",
"1": "<",
};
var vm = this;
vm.filterOptions = {
"operators": {
"type1": ["0", "3"],
"type2": ["1", "2", "3"]
},
"keys": [
{
"datatype": "type1",
"name": "a",
"column": "col1"
},
{
"datatype": "type1",
"name": "b",
"column": "col2"
},
{
"datatype": "type2",
"name": "c",
"column": "col3"
}
]
};
vm.filters = [];
//vm.removeFilter = removeFilter;
//vm.addFilter = addFilter;
vm.getOperators = getOperators;
function getOperators(keyIndex) {
var operators = [];
var dataType = vm.filterOptions.keys[keyIndex].datatype;
if (vm.filterOptions.operators[dataType]) {
angular.forEach(vm.filterOptions.operators[dataType], function (operator, index) {
var obj = {};
obj[dataType] = (operatorMap[operator] ? operatorMap[operator] : operator);
operators.push(obj);
});
}
return operators;
}
(function init() {
// I am actually getting the filterOptions with a REST call, but I've included the data already
// The following is done after the successful REST call
// add the first filter
var filter = defaultFilter;
filter.operator = Object.keys(getOperators(filter.keyIndex))[0];
vm.filters.push(filter);
}).call();
});
Here's a plunker: https://plnkr.co/edit/yGyvwThuWWnNph72OAT0
Okay, so I figured this out.
First, don't generate an array in the getOperators method. You can return and array that is already defined, but you can't generate a new array here. This leads to an indefinite loop as angular detects a change and call the getOperators method again.
So what I did was...
after the data was fetched from the REST service, I call a function "transformOperators". This implements the looping I was doing in "getOperators" and stores this "transformed data" in a class level object.
in "getOperators" I simply do an object lookup and return the results.

AngularJs - How can i fetch the value from one input field into another field using angular.copy?

I am not able to copy a value from one field into the next. I used typeahead in po num. If I select po num value from typeahead simultaneously the quantity value is autofilled, and the value for copied quantity needs to be copied from the quantity. This is the link to ...my plunk...please help me on this issue. For instance:- If I select po num as 1356 from drop-down, the quantity value is fetched automatically gives as 100. I want the copied quantity value to reflect the same as 100.
I've Added the code that I've used below. Please do have a look and let me know where I've made the mistake. I know it could be something insanely small as well, please do help. Thanks in advance
my plunk
Controller:-
$scope.$watch('states.purchase_order_details_ord_no', function() {
if($scope.state && $scope.states.purchase_order_details_ord_no && $scope.states.purchase_order_details_ord_no.getTotalsshadeqty) {
$scope.copied = angular.copy($scope.states.purchase_order_details_ord_no.getTotalsshadeqty);
} else {
$scope.copied = null;
}
});
Html:-
<div ng-repeat="states in states.pocomments">
<label for="purchase_order_details_ord_no">po num</label>
<input type="text" ng-model="states.purchase_order_details_ord_no" id="purchase_order_details_ord_no" typeahead="type as type.purchase_order_no for type in types | filter: $viewValue">
<label for="quantity">quantity</label>
<input type="text" id="supname" ng-model="states.purchase_order_details_ord_no" typeahead="type.getTotalsshadeqty for type in types | filter: $viewValue">
<label for="quantitycopy">Copied quantity</label>
<input type="text" name="supnamecopy" id="supnamecopy" ng-model="copied">
</div>
My data:-
$scope.types = [
{
"_id": "5768e6c8bdbc5db509f0f2b2",
"created": "2016-06-21T07:03:36.504Z",
"getTotalsshadeqty": "100",
"getTotalsprice": "1000",
"getTotalsqtyprice": "100000",
"purchase_order_no": "1356",
},
{
"_id": "5767cd78f5012d790aa41a7b",
"created": "2016-06-20T11:03:20.382Z",
"getTotalsshadeqty": "12",
"getTotalsprice": "10",
"getTotalsqtyprice": "120",
"purchase_order_no": "0987",
}];
$scope.states = {
"_id": "575691b26a5ec735128fe635",
"pocomments": [
{
"_id": "575691d56a5ec735128fe636",
"po_value_currency": "Rs",
"value": "124",
"rate": "24",
"quantity": "",
"purchase_order_details_ord_no": ""
},
]
ng-repeat creates an isolated scope for the children created.
You need to add a $parent to the accessor of your model-properties if you want to change properties outside of the isolated scope.
Eg. ng-model="$parent.states.purchase_order_details_ord_no"
Additionally inside your watch-expression you mistyped states (you checked for state).
Fork that should work as expected: http://plnkr.co/edit/QAgJZToxkqvtg7pFSseO?p=preview

Generate JSON using jQuery

I have 4 inputs in a form:
<form id="mark_date_form">
<input type="text" name="title" class="form-control" placeholder="Title" value="motherday">
<input type="text" name="date" class="form-control datepick" placeholder="MM/DD" value="05/13">
<input type="text" name="title" class="form-control" placeholder="Title" value="fatherday">
<input type="text" name="date" class="form-control datepick " placeholder="MM/DD" value="06/18">
</form>
When I use $('#mark_date_form').serializeArray() in jQuery, it returns
[
{
"name": "title",
"value": "motherday"
},
{
"name": "date",
"value": "05/13"
},
{
"name": "title",
"value": "fatherday"
},
{
"name": "date",
"value": "06/18"
}
]
The question is I have to come out with something like this:
[
{
"title": "motherday",
"date": "05/13"
},
{
"title": "fatherday",
"date": "06/18"
}
]
What should be the jQuery looks like?
Thank you very much!
I think you are looking for this $("#mark_date_form").serialize();
Update: sorry for the #daniel-cai is correct.
Use $("#mark_date_form").serializeArray(); for getting JavaScript literal object.
You can use this:
var a = [];
$('#mark_date_form input').each(function(){
if($(this).attr('name')=='title'){
a.push({"title":$(this).val(),"date":$(this).next().val()});
}
});
console.log(a);
Output:
[Object { title="motherday", date="05/13"}, Object { title="fatherday", date="06/18"}]
Simple way to get a json file as you want is:
var o = {};
$("#mark_date_form").serializeArray().map(function(x){o[x.name] = x.value;});
console.log(o);
Result:
Object {title: "motherday", date: "05/13"}
DEMO: http://jsfiddle.net/gon250/s3xerkgc/1/
Hope it's helps.

Categories