Create JSON object from Dynamic NgModel - html

I have a service which returns a JSON of type array[obj1{name, usage, id}, obj2{name, usage, id}] on HTML page I am creating a form with form field = name and it is pre-populated with value = usage. Ex: if there are 2 objects inside array where name1=a usage1=1 and name2=b and usage2=2, 2 form fields will be created. Form field names will be name1 and name2 and will be filled already with usage1 and usage2 value respectively. I am doing this with this code:
<form>
<div class="form-row">
<div class="form-group" *ngFor="let item of items">
<label>{{item.name}}</label>
<input type="number" min="0" [id]="item.name" [name]="item.name" class="form-control" [(ngModel)]="item.usage">
</div>
</div>
</form>
It is working fine. Now suppose user changes the value for usage1 and usage2. On submit button I have to create a json object in typescript and send it in the API. I am facing issues to create the JSON object. I have tried:
onSubmit{
this.changedValues = this.items.usage;
console.log(this.changedValues);
}
But console.log return undefined. Json object I am expecting should be something of they type:
changedValues[{upadatedUsage1, id1},{updatedUsage2, id2}]
How can I create a json object dynamically and also how can I send the correct id with the correct updated usage value. Thank you

The reason for undefined value is that, items is an array and hence doesn't have the property usage
onSubmit {
this.changedValues = this.items;
console.log(this.changedValues);
}
This should give the array with updated values.

Related

Thymeleaf: Iterate over enum values and use them in a list filter

I am struggling using enum values in list filters in Thymeleaf.
I know how to iterate over enum values and how to compare them against constant values. However, I want to compare it against a 'variable' value. How can I achieve it?
In my example below, I want to iterate trough all colors (enum) and then filter a list of cars by the current color enum and display their names.
How do I specify the list filter in the second <div> correctly?
<div th:each="currentColorEnum : ${T(de.my.enum.color).values()}">
<div th:each="currentCar, carStatus : ${model.carList.?[#this.colorEnum eq __${currentColorEnum}__]}">
<textarea th:field="*{carList[__${carStatus.index}__].carName}"></textarea>
</div>
</div>
Current error message:
org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'red' cannot be found on object of type 'de.my.class.car' - maybe not public or not valid?
No need for preprocessing in this case. It's failing because ${model.carList.?[#this.colorEnum eq __${currentColorEnum}__]} resolves to ${model.carList.?[#this.colorEnum eq red]}. Which means it looking for cars where car.colorEnum == car.red -- hence the error field 'red' cannot be found on object of type 'de.my.class.car'.
Your Thymeleaf should look something like:
<div th:each="currentColorEnum : ${T(de.my.enum.color).values()}">
<div th:each="currentCar, carStatus : ${model.carList.?[colorEnum eq #root.currentColorEnum]}">
<textarea th:field="*{carList[__${carStatus.index}__].carName}"></textarea>
</div>
</div>

How to slice date string before parsing it to datetime-local input

I want to edit or change date of a json object but because of the long milliseconds string, the datetime-local could not display the date. Is there a way to first remove three(3) numbers from the milliseconds string before I parse the date string to form input.
json
{
"appointment": "Dentist",
"date": "2007-04-30 13:10:02.047438"
}
comp.ts
showDetail(data: any) {
this.formData.controls.appointment.setValue( data.appointment );
this.formData.controls.date.setValue( data.date ); //here the datetime-local could not read .000000 millis, I need to remove last 000
}
.html
//....
<div class="form-group">
<label>Date:</label> <input type="datetime-local"
value="2007-04-30T13:10:02" class="form-control"
formControlName="date" required>
</div>
I have in the DB e.g 2007-04-30 13:10:02.047438 but I want to slice to 2007-04-30 13:10:02.047 in my .ts file, so that my form can display the date when showDetails function is called.
You can use substr() like so:
let str = "2007-04-30 13:10:02.047a438";
str.substr(0, str.length-3);
Here's the matching documentation
If you want to avoid trimming the length a better approach would be using Angular Date Pipe filter. you can display in various formats as per your choice. you can check it out here DatePipe

Angular2 Reactive forms, FormControl default value in pristine status

I have created a form which allows the user to add additional text-inputs by clicking a button. The FormControls behind these inputs are stored in a FormArray inside of a FormGroup.
I want to provide a default value for these inputs, that is going to be submitted if they are pristine. If the user changes the value of the input, which changes it to dirty, I do not want the default value to be submitted or displayed.
I currently am displaying the inputs like this, as the placeholder attribute does exactly what I want, displaying the default name, only if the input has not been changed.
<div
formArrayName="names"
*ngFor="let server of names.controls; let i = index; trackBy:trackByFn">
<span>{{ i + 1 }}</span>
<input
type="text"
formControlName="{{i}}"
placeholder="{{defaultName}}">
</div>
To validate the names I have created the following validation function:
export function validateServerName(form: FormGroup): ValidationErrors | null {
const names: string[] = form.value[CREATE_FORM_KEY_NAMES];
for (const name of names) {
if (name.trim() === '') {
return {
invalidName: true
};
}
}
return null;
}
Here I am having trouble figuring out if the element is dirty or pristine, as form.value[key] only returns a string array, not an array of the FormControls.
I am looking for either an easier way to do what I am trying to achieve, or a way to validate the form properly.
you can check the control status using
if touched is true then its dirty
this.form.get('controlname').touched
and for pristine you can check like
this.form.get('controlname').pristine
UPDATE
for form array it will be something like
let val = this.user.get('<FormArray>') as FormArray;
console.log(val.at(index));
you can now use pristine and touched on this variable

MVC: Pass ViewData object with type 'double' to number input field

I’m trying to pass a ViewData object of type double to an input field of type number with 1 decimal place. But the input field keeps empty. What am I doing wrong?
<p>
Debiet factor: <input name="FlowFact" type="number" value="#ViewData["FlowFact"]" step="0.1" autocomplete="off">
#String.Format("{0:N1} m³/h", #ViewData["FlowFact"]) <!--Result = 3,1 m³/h-->
</p>
The issue you're facing is what the ViewData["FlowFact"] is returning, which according to your #String.Format("{0:N1} m³/h", #ViewData["FlowFact"]) <!--Result = 3,1 m³/h--> it's 3,1.
That is not recognised as a number so it won't work. Either return a whole number or a decimal number. So instead of a 3,1, return a 3.1 or just a 3.
Otherwise change the input type to accept what you are passing.
I found the solution thanks to jamiedanq.
In my controller I was writing a double value to the #ViewData["FlowFact"] object. But in my view it was returning a value 3,0999 , which is not a correct value for the input type 'Number' because of the ",".
Instead of passing a double value to the object I've changed it to pass a string value and replace the "," with a ".":
Controller:
#ViewData["FlowFact"] = #String.Format("{0:N1}", MyDoubleValue).Replace(",",".");
View:
<p>
Debiet factor: <input name="FlowFact" type="number" value="#ViewData["FlowFact"]" step="0.1" autocomplete="off">
</p>

Angular: Push Generated Timestamp on Submitted Form

I've written a form in Angular that sends submitted data in my form to an object called places in my Firebase.
HTML
<form role="form" name="addPlaceForm" ng-submit="createHospital(newHospital)">
<input type="text" placeholder="Enter title here" ng-model="newHospital.title">
<button type="submit" class="btn btn-primary btn-lg">Submit</button>
</form>
JS
var rootRef = new Firebase('URL');
var placesRef = rootRef.child('places');
function createHospital(hospital) {
placesRef.push(hospital);
}
Is there a way I can push a generated timestamp called created_at to my places object when it's submitted?
"created_at" : "2014-07-15T01:52:33Z"
And what about other automated data, like pushing a unique ID, for example.
Any help with this would be appreciated. Thanks in advance!
Is there a way I can push a generated timestamp called created_at to my places object when it's submitted?
An alternative to passing the timestamp from the client is to use Firebase's built-in Firebase.ServerValue.TIMESTAMP, which is documented as:
A placeholder value for auto-populating the current timestamp (time since the Unix epoch, in milliseconds) by the Firebase servers.
So you could do something like this:
function createHospital(hospital) {
hospital.created_at = Firebase.ServerValue.TIMESTAMP;
placesRef.push(hospital);
}
See this post for more information:https://www.firebase.com/blog/2013-06-17-howto-build-a-presence-system.html
What about other automated data, like pushing a unique ID?
When you call the Firebase push method a unique ID is already generated for you. The documentation for push:
Generates a new child location using a unique name and returns a Firebase reference to it.
This ID is guaranteed by Firebase to be unique, specifically so that your application doesn't have to worry about it. The push-generated ID takes a form like -JXd1pbUU89Xbd4BYvx6, -JZoLcBKnd1A8Gn-ZP0I, etc.
I would recommend sticking to that ID, instead of generating your own additional ID. If you prefer to to generate your own IDs, I would solely use that ID and use it to name your node instead of letting push generate one for you:
var newID = ID_GENERATE_FUNCTION();
placesRef.child(newID).set(hospital);
Note that here too I don't store the newID in the hospital object.
Right when you add the hospital to the array you can create the two parameters you want:
function createHospital(hospital) {
var newHospital = angular.copy(hospital);
newHospital.created_at = new Date();
newHospital.ID = ID_GENERATE_FUNCTION();
placesRef.push(newHospital);
}