Using ng-model on a dictionary value within an array - javascript

So I have an array that I've populated like so:
tempArray[tempProductName] = null;
tempArray[tempAttributeName] = response.data[0].Attributes[k].Name;
tempArray[tempAttributeValue] = null
$scope.newDayDisplay.push(tempArray);
I'm using this information in an ng-repeat like so:
</div>
<div class="row" ng-repeat="result in newDayDisplay">
<div class="col s2">
<md-input-container><label>{{result.AttributeName}}</label><input type="number" id="new-day-ARP-input" ng-model="result.AttributeValue" /></md-input-container>
</div>
<div class="col s4">
<label>Select Material</label>
<md-select ng-model="result.ProductName" md-on-close="clearSearchTerm()" data-md-container-class="selectdemoSelectHeader">
<md-select-header class="demo-select-header">
<input ng-model="searchTerm" type="search" placeholder="Search For Material..." class="demo-header-searchbox md-text">
</md-select-header>
<md-option ng-value="{{mat.ID}}" ng-repeat="mat in Materials | filter:searchTerm">{{mat.Name}}</md-option>
</md-select>
</div>
<div class="col s2">
<p>{{result.AttributeValue}}</p>
<p>{{result.ProductName}}</p>
</div>
</div>
The issue is that whenever I try to send this information as a post (the array) it does not bind the values for result.AttributeValue or result.ProductName to the respective value in the array "newDayDisplay".
So for example, I get
But I want to be able to change those null values to the values entered on the modal.
I imagine this has to do with ng-repeat not working the way that I think that it does - does anyone know how to fix this?
Note that even if I do:
<div class="col s2">
<p>{{result.AttributeValue}}</p>
<p>{{result.ProductName}}</p>
</div>
I'm able to see the values I've selected, but the post doesn't take the values with it.
Here's an example of that binding:

Related

ngModel is reflecting to all textareas

I have multiple textareas (looping with ngFor and adding new divs with textareas inside). What i need is for every textarea to have separate ngModel and i don't want to directly bind this to property from object in dataArray - for example:
[(ngModel)]='data.note' or [(ngModel)]='data.feedback' .
This works but I don't have feedback property in dataArray so it won't for work for second textarea.
For example with my current implementation change in one textarea is reflecting in all other textareas. I tried with index approach but getting error:
ERROR TypeError: Cannot read property '1' of undefined
<div *ngFor="let data of dataArray; let index=index;trackBy:trackByIndex;">
<div class="card-body">
<form class="form">
<div class="form-body">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<textarea name="note" [(ngModel)]='selectedNote' class="form-control"
rows="2"></textarea>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<textarea name="feedback" [(ngModel)]='selectedFeedback' class="form-control" rows="4"></textarea>
</div>
</div>
</div>
</div>
</form>
</div>
With current code if i add some text in first textarea with name 'note' that change is reflected for all textareas with name 'note'. As mentioned tried with adding
[(ngModel)]='selectedFeedback[index]' but i am getting error.
Also tried with giving different names to textareas:
<textarea name="note{{index}}" [(ngModel)]='dataArray[index]' rows="2"></textarea> OR
<textarea name="note{{index}}" [(ngModel)]='selectedNote' rows="2"></textarea>
but change is reflecting for each textarea again.
You can try it with any array, I am using data(n) function to return an Array of length n. In this example it's just for iteration
<div *ngFor="let item of data(8); let i = index">
<textarea [(ngModel)]='values[i]'></textarea>
</div>
// To reflect changes
<div *ngFor="let item of data(8); let i = index">
<div>{{ values[i] }}</div>
</div>
With TS
export class AppComponent {
values = [];
data(n) {
return Array(n);
}
}
Working example in Stackblitz.com
ngModel binds with the name property. So if you want to use multiple textarea try using different name attribute. You can iterate over like -
<ng-container *ngIf="let data of dataArray; index as i">
<textarea name="feedback_{{i}}" [(ngModel)]='selectedFeedback' class="form-control" rows="4"></textarea>
</ng-container>

Razor View - jQuery .val() is updating some components visually -- but not all

I have a search feature built into a page that hits an API to get a list of items if a user chooses to search instead of manually enter (in an attempt to get some clean data). I have the first column of said table set to call a JavaScript function onclick. That function looks similar to this:
function loadDataFromTable(fname, lname, mname, stn, grade, school) {
$('#StudentFirstName').val(fname);
$('#StudentLastName').val(lname);
if (mname !== "undefined") {
$('#StudentMiddleName').val(mname);
}
else {
$('#StudentMiddleName').val('');
}
$('#StudentNumber').val(stn);
$('#Grade').val(grade);
$('#School').val(school);
return false;
}
The associated HTML elements are all ASP.NET Core Razor View input elements. They look like this:
<div class="form-group">
<label class="col-md-3 control-label">Last Name</label>
<div class="col-md-9">
<input type="text" asp-for="StudentLastName" class="form-control" />
<span asp-validation-for="StudentLastName" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label class="col-md-3 control-label">STN</label>
<div class="col-md-9">
<input type="text" asp-for="StudentNumber" class="form-control" />
<span asp-validation-for="StudentNumber" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label class="col-md-3 control-label">Grade</label>
<div class="col-md-9">
<input type="text" asp-for="Grade" class="form-control" />
<span asp-validation-for="Grade" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="School" class="col-md-3 control-label"></label>
<div class="col-md-9">
<select asp-for="School" asp-items="ViewBag.SchoolList" class="form-control"></select>
<span asp-validation-for="School" class="text-danger"></span>
</div>
</div>
Now, if a user clicks on one of the links from the table, all of the values are properly passed into the function, and all of the values for First Name, Last Name, Middle Name, and STN properly update on the view. Grade and School do not update on the View, but their value attribute does update. When I submit the form after the data fills, the correct values are passed to my controller.
What I can't figure out is why the Grade and School values are not populating on the view. The only thing that stands out as different for these two are within the model they are nullable integers, whereas other fields are strings.
I have tried a mixture of .attr('value', grade), .text(grade), and .val(grade), and none of them are working. I can verify that the proper elements are being selected because if I output $('#Grade') I get the input object.

Expression in ng-model AngularJS

I need to execute an expression inside ng-model.
I have an array of integers which is shown in a list and input fields needs be generated on click of each item. All input fields should carry a generated value of ratio having base as 1. I also need to get the sum of numbers in the input field since the user can change the value.
My Code for this is
<div class="row" ng-repeat="kpi in SelectedKpiModel">
<div class="small-2 columns" ng-click="View.RemoveSelectedKPI($index)" style="margin-top:0.5em;border:ridge;padding-bottom: 1em; padding-top:0.5em; text-align:center"><span class="fa fa-scissors"></span></div>
<div class="small-4 columns" style="margin-top:0.5em;border:ridge;padding-bottom: 1em; padding-top:0.5em; text-align:center">
{{kpi.id}}
</div>
<div class="small-4 columns" style="float:left;margin-top:0.5em;border:ridge; padding:0em">
<input type="number" value="{{1/SelectedKpiModel.length}}" />
</div>
</div>
How do I get the count of all the field values if user changes or how do I store the value of each field and retrieve if need ?
I tried like ng-model="{{1/SelectedKpiModel.length}}" but it gave me error.
Thanks.
You can use something like this -
<input type="number" ng-model="getLength()" />
and your function -
$scope.getLength = () => {
return 1 / $scope.SelectedKpiModel;
}

Validate a form field with a dynamically given name in angular

I create a form dynamically in the view by iterating through an object that has the different questions to be asked to the user. One of the attributes of every question is formFieldName which is a a random string I use to give each form field a different name.
<form name="includedForm.newRequestForm" class="form-horizontal" role="form" novalidate>
<div ng-if="message.question.attributes.structure.type == 'object'">
<div ng-repeat="(index,objField) in message.question.attributes.structure.properties">
<div ng-if="objField.type == 'array'" class="form-group" show-errors>
<label for="{{objField.formFieldName}}" class="control-label col-sm-6">{{objField.title}}
<br /><i><small>{{objField.description}}</small></i></label>
<div class="col-sm-6">
<select class="form-control" name="{{objField.formFieldName}}" multiple ng-model="objField.userValue" ng-required="objField.required">
<option ng-repeat="option in objField.items.enum" value="{{option}}">{{option}}</option>
</select>
</div>
</div>
<div ng-if="objField.type == 'boolean'" class="form-group" show-errors>
<label for="{{objField.formFieldName}}" class="control-label col-sm-6">{{objField.title}}</label>
<div class="col-sm-6">
<input class="form-control" name="{{objField.formFieldName}}" ng-model="objField.userValue" type="checkbox" ng-value="option" ng-checked="message.question.attributes" />
</div>
</div>
</div>
</div>
<div class="col-sm-12">
<button ng-click="markAsDone(message)" class="btn btn-primary">Done</button>
</div>
<form>
In the controller I'm able to get the formFieldName attribute but I can't figure out how to use it to do the validation.
var MarkAsDone = function(message) {
$scope.includedForm = {};
var formField = message.question.attributes.formFieldName;
if ($scope.includedForm.newRequestForm.{{formField}}.$valid){
//submit the form
}
}
to answer you question:
first, {{}} is === $scope so you don't use that anywhere other than HTML. You use $scope in your JS and {{}} in HTML which creates a pipe (2-way binding) so that $scope.variable.property has bidirectional binding to {{variable.property }} in HTML.
$scope.includeForm.email === {{ includeForm.email }} === ng-model="includeForm.email" === ng-bind="includeForm.email"
if you set anyone of those all are set so if you set $scope it will show up in HTML and obviously as user input gets captured it is already in $scope ... all connected
when attempting to get the value from HTML back into JS you would need create and set a $scope i.e so if you create $scope.dataModel.dataProperty and use that in ng-model=dataModel.dataProperty (example) you again have two way binding ... you don't need to do anything as angular is taking care of the data pipeline. So if you want to extract the value to var, which is probably a waste as the $scope is already set as soon as the user checks the box
var formField = $scope.dataModel.dataProperty;
// but like I said no need as $scope.dataModel.dataProperty; is your var
In JS if you want to use a dynamic property as an object property key you would place the dynamic value in [] e.g.
$scope.variable[dynamicProperty].method;
// you can set a static property as a key with dot notation i.e.
$scope.variable.staticProperty = val;
Hope that helps

How to bind data once selected from search using AngularJS?

I have search functionality on one of the field once user finished search and selected the value from the data grid i am populating value into field, So I am printing value in console correctly console.log($scope.challengesDTO.chlgOwner) but its not binding it to view model challengesDTO.chlgOwner
main.html
<div class="row">
<div class="form-group col-md-12 fieldHeight">
<label for="chlgOwner" class="col-md-4">Challenge Initiated on behalf of:</label>
<div class="col-md-8">
<input type="text" class="form-control" id="chlgOwner"
ng-model="challengesDTO.chlgOwner" ng-click="openChallengerSearch()"
name="chlgOwner">
</div>
</div>
searchCtrl.js
$scope.selectedChallenger = function(workerObj) {
$scope.challengesDTO.chlgOwner = workerObj.fullName;
$scope.challengesDTO.chlgKey = workerObj.workerKey;
console.log($scope.challengesDTO.chlgOwner);
$scope.viewChallengeWin.close();
};

Categories