populate FormBuilder from a service in Angular2 - javascript

I have an Angular2 model that I'm populating via a service. I would like to use this model to then populate my form (built from FormBuilder) so my users can edit the data.
Here is what I am currently doing, but I get errors for fields that exist in my model that are not being exposed in my form.
...
ngOnInit(): void {
this.buildForm();
this.get('1');
}
get(id: string) {
this.myModelsService.get(id)
.subscribe(
d => {
this.myModel = d;
this.myForm.setValue(d);
},
error => console.log(error)
);
}
This works, however I get errors like Cannot find form control with name: incidentTimeStamp.
Should I be first deleting attributes that I know do not have corresponding form controls? Or is there a better way to do what I am trying to do?
Being able to populate fields for edit seems like a pretty basic building block, and this seems like it is way harder than it should be.

The solution is to use FormGroup.patchValue()
FormGroup.setValue() does strict checks, while FormGroup.patchValue() does not.

Related

Angular 10+ checkbox filtering

I'm trying to implement multiple checkbox filtering using Angular but can't seem to be able to figure out how to proceed exactly. I've looked over multiple similar questions here, but failed to figure out how to use any of the answers.
Ideally, I'd like to filter my data using event listeners.
My main two issues are:
Figuring out how to actually filter things, I can't figure out what the right approach would be for my goal
Actually displaying updated data
Stackblitz
Any push in the right direction would be greatly appreciated!
Basically, you need to share the data(filters) between two components because filtered-users and filters are two components in your project.
so, to share data between two components (which are not having parent-child relationship) we can use observables.
You can create a service called FilterService and in that, you can have an observable (filters)
#Injectable()
export class FilterService {
private filters = new Subject<{}>(); // creating a subject
filters$ = this.filters.asObservable(); // creating an observable
alertFilter(key: string, value: string) {
this.filters.next({ key, value }); // publishing the new fliter to the subscribers
}
}
and add this service to filtered-users, filters components through dependency-injection. and call this alertFilter() method of FilterService from filters component whenever the user checks the filter checkbox.
in filter.component.html
<input (change)="onCheck('gender', opt)"
in filter.component.ts
onCheck(key: string, value: string) {
this.filterService.alertFilter(key, value);
}
after this, subscribe to the observable(filters) of FilterService in filtered-users-component.
in filtered-users.component.ts
constructor(
private sortingService: SortingService,
private userService: UserService,
private filterService: FilterService
) {
this.filterService.filters$.subscribe({
next: filter => {
this.filteredUsers = this.filteredUsers.filter(user => {
return user[filter['key']] === filter['value'];
});
}
});
}
this.filterService.filters$.subscribe() will execute whenever a new filter has been added so, using filter variable you can filter the users accordingly.

Upload search results data in angular with a button click

I am having a project requirement on Angular. I am using search option where I am able to search data from external api and display user below it when clicking on Add button. I tried implementing using angular primeng autocomplete.
But problem is that as per the screenshot here https://imgur.com/a/wXYqOpM
When I clicked on Upload List, all the user data displayed should be uploaded with a button click (either as file or array). Since I am new to angular, can you help me to find a suitable solution for the same?
Thanks in advance
Patric
There's a bit more input needed in order to properly, entirely answer your question. I'll just make a couple assumptions to do so.
I suppose that you're having an array of patients/users in your .ts file and display that data in your .html using data interpolation. Something like this:
upload-list.component.ts:
...
public userList = ['Patient 1', 'Patient 2', 'Patient 3']
...
upload-list.component.html:
...
<your-list-display>{{ userList }}</your-list-display>
<button (click)='sendData()'>Upload list</button>
Eventually, all you need to do is inject the HttpClient (imported from #angular/common/http) into your component's constructor and use it (preferably in a service, read up in the angular.io docs for that specifically, how to share data between components etc).
Roughly outlined, something like this shall work:
upload-list.component.ts:
import { HttpClient } from '#angular/common/http';
...
export class UserList {
constructor(private http: HttpClient) {}
public sendData(): void {
this.http.post<any>(apiURL, this.userList).subscribe(result => {
... // do something with the result from your HTTP request.
}, error => {
... // handle error as wished
});
}
}
Hope that'll help - Regards
EDIT - moved API call into function which'll be called upon button click

Submitting a post that belongs to current user - how to define the relation on client-side in Vue?

Im building an app using Node.js, specifically Express server-side and Vue client-side, with SQLite + Sequelize for managing the database.
Part of the functionality is that a user can make a post. This is currently possible but I needed to implement a relation so a post can be associated with the author.
I did this server-side in sequelize and all seems to be well on that end as the table columns all look correct with foreign key and references etc.
So now I need to somehow presumably set the current UserId for the post before it gets submitted. Here is the script element for the Vue component which is to be used as the interface to make posts.
<script>
import PostService from '#/services/PostService'
export default {
data () {
return {
post: {
title: null,
body: null
}
}
},
methods: {
async submit () {
try {
await PostService.post(this.post)
} catch (err) {
console.log(err.response.data.error)
}
}
}
}
</script>
I'm using Vuex to manage the state, where the 'user' object response from the database upon login is stored as simply user in my store.
So I was guessing all I had to do was the following to access the user:
post: {
title: null,
body: null
UserId: this.$store.state.user.id
}
The problem is any time I insert this line, the component stops working in some way. Doing as above stops the component displaying at all. So I tried setting it to null as default, then instead doing this inside my submit method:
this.post.UserId = this.$store.state.user.id
If I do this, the component displays but the submit method no longer runs; I also tried both these methods without the .id just incase, no difference.
I then tried removed from the data model completely, after reading that sequelize may be generating a setUser method for my post model. So tried the following in submit method before sending the post:
this.post.setUser(this.$store.state.user)
... again the method stops running. Again, even if adding .id.
Without trying to set any ID at all, everything works until the server returns an error that 'Post.UserID cannot be null', and everything worked perfectly before I implemented the relation.
I haven't really found anything useful beyond what I already tried from doing a few searches. Can anyone help out? I'm totally new to Node.
I have accessed other parts of the state such as isUserLoggedIn, and it all works fine and no crashes occur in those cases.
I just managed to get it working correctly, I'm not sure why it suddenly started working as I am sure I had tried this before, but I solved it by doing the following within my component's script element:
<script>
import PostService from '#/services/PostService'
export default {
data () {
return {
post: {
title: null,
body: null,
UserId: null
}
}
},
methods: {
async submit () {
this.post.UserId = this.$store.state.user.id
try {
await PostService.post(this.post)
} catch (err) {
console.log(err.response.data.error)
}
}
}
}
</script>
Posts now create and display as normal. If anyone knows anything I'm technicially not doing right in any of my approach though please let me know, as I am still learning Node, Express and Vue.

Angular2 ng2-auto-complete display and selection issues

I have implemented the Angular 2 ngui-auto-complete component by following this component. And related to this i found example. But the issue I'm facing is, on my auto-complete there multiple dependencies. So for that on selection I want id but I am not getting on selection id.
And one more facing issue is my source is in the form of an object with id as one of the fields. And by following the implementation example of the component, the id is displayed in parenthesis in the dropdown. Is there a way to not display the id in the dropdown?
Here is my HTML code for the auto-complete component:
<input class="text-uppercase form-control" ngui-auto-complete [(ngModel)]="shipper.cust_name" [source]="shipperNameSource.bind(this)" value-property-name=null value-formatter="cust_name" min-chars="1" (change)="updateShipperDetails()"/>
My component
shipperNameSource = (keyword: any): Observable<any[]> => {
let url: string =
'api/getCustomers?selected='+keyword
if (keyword) {
return this.http.get(url)
.map(res => {
let json = res.json();
this.customer.id = json.id;
return json;
})
} else {
return Observable.of([]);
}
}
This is what I get
There is nothing wrong with your data. It is showing undefined means your data exist but there is something wrong with your mapping with auto-complete. Trying to log api response and check in which node you are getting actual data and map accordingly.

Get returned object from controller into the javascript

In my controller, I send an object list into the view (index.cshtml)
return View(AdsPrevModel);
in my index.cshtml:
<div id ="ele">
<ul>
<li> name1<input id="a1" type="checkbox"/></li>
</ul>
</div>
when the user clicks the checkbox, I use jquery to know if the user checked the box or not:
My javascript file:
$('#ele :checkbox').click(function () {
if ($(this).is(':checked')) {
alert($(this).attr('id'));
} else {
alert('unchecked');
}
});
How can I get my AdsPrevModel into my js file?
I know I can do something like this:
In my html, add:
<input type="hidden" id="AdsPrevModel" value="#Model.AdsPrevModel" />
and in the js:
var adsPrevModel = JSON.parse(document.getElementById('AdsPrevModel').value);
Is there another option without adding a hidden input in my html?
Maybe something like the following in the js file:
var adsPrevModel = JSON.parse(Model.AdsPrevModel));
The best practise is
do an ajax call to that controller and that controller should return json results
return JSON( model ) ;
In the code you've shared there's nothing emitting the model to the client, so there's currently no direct way for the JavaScript code to access it.
Since you're binding the view to the model, the view can include it in various ways. It could be a series of hidden fields for the members of the model (not the model in its entirety, unless it can be represented as a string in its entirety). Something like this:
#Html.HiddenFor(x => x.SomeField)
#Html.HiddenFor(x => x.AnotherField)
This would create two hidden inputs for two fields on the model. Depending on how complex the model is, this could get cumbersome.
You might also emit the model to the JavaScript code directly in a similar fashion:
var someField = #Model.SomeField;
var anotherField = #Model.AnotherField;
Again, if the model is complex, this gets cumbersome quickly. Even if you try to build an actual JavaScript object from it:
var theModel = {
someField : #Model.SomeField,
anotherField : #Model.AnotherField
};
(Note also that I've seen Visual Studio get very confused when you mix razor syntax and JavaScript like this. Not so much in 2012 anymore, but a lot in 2010.)
You might use something like the JavaScriptSerializer to add a property on the model for a serialized version of itself. I've never done this before, but it should work. Something like this on the model:
public string SerializedCopy
{
get
{
return new JavaScriptSerializer().Serialize(this);
}
}
It might take some tweaking to get it to work, though.
Finally, a particularly clean option which only requires another request to the server would be to have another action which just returns the JSON version of that model. Something like this:
public ActionResult SomeActionName()
{
// get the model somehow, then...
return Json(AdsPrevModel);
}
Your JavaScript code would then just need to call this action to get the JSON object representing the whole model:
var theModel = {};
$.get('#Url.Action("SomeActionName", "SomeController")', function (data) {
// maybe do some error checking here?
theModel = data;
});
Then if your actual view isn't actually binding anything to the model then the action which returns that view doesn't need to fetch the model and supply it to the view. The JavaScript code would get the model by calling this other action which returns JSON data instead of a view.

Categories