Angular form reset() doesn't sets controls to empty - forms

I'm referring to Hero guide passing the object to empty all the fields in the model like this.
this.form.reset({
"firstName": "",
"lastName": "bzz",
"reporter": ""
});
The problem is that it only sets the fields that are non-empty, i.e. bzz in the sample above. I've tried with setValue(...) but that gave the same effect. Goolearching the issue gave rather nothing other than references to the Hero examples.
I also tried to use the following. Same effect as well.
this.form.get("firstName").patchValue("");
What am I missing?

Don't pass an object, and It will set all the form controls to null:
this.form.reset();

this.form.reset({
firstName: {value: '1', disabled: true}
})

Related

How to filter an array of object in Mui DataGrid?

I recently changed my tables to Mui-datagrid on Material UI 5, and I have a special use case with an array of objects. I want to enable the phone number filter in this column, but the number is provided as an object list.
phone: [
{ type: "home", number: "795-946-1806" },
{ type: "mobile", number: "850-781-8104" }
]
I was expecting a 'customFilterAndSearch' or an option to customise how to search in this specific field.
customFilterAndSearch: (term, rowData) =>
!!rowData?.suppressedOptions.find(({ description }) =>
description?.toLowerCase().includes(term.toLowerCase())
),
I have made some tries with the filterOperators, but no success yet. I have made a full example here https://codesandbox.io/s/mui-data-grid-vs05fr?file=/demo.js
As far as I can see from the DataGrid documentation I don't see any way to change the filter function for a specific function.
Likely the best workaround for your use case will be converting this to a string be converting the data to a string before you pass it to the datagrid. Though you will lose the styling that you currently do by making the phone type bold.
On second though your best best would probably be to split the phone column into two columns which would probably be the cleanest way of solving your problem
Add helper function.
You could potentially add a helper function to just map all the phone lists to something like mobilePhone or homePhone
const mapPhoneObject = (rows) => {
rows.forEach((row) => {
row.phone.forEach((phone) => {
row[`${phone.type}Phone`] = phone.number;
});
});
return rows
};
I've added a fork of your snippet with my function, it is I think the most viable solution for your problem: https://codesandbox.io/s/mui-data-grid-forked-ppii8y

Apigility: How to render embedded objects?

How do I render embedded objects in Apigility? For example, if I have a 'user' object and it composes a 'country' object, should I be rendering the 'country' object as an embedded object? And how should I do this?
I am using the Zend\Stdlib\Hydrator\ArraySerializable. My getArrayCopy() method simply returns an array of properties that I want exposed. The array keys are the property names. The array values are the property values. In the case of user->country, the value is an object, not a scalar.
When I return the user object from UserResource->fetch(), here's how it is rendered:
{
"id": "1",
"firstName": "Joe",
"lastName": "Bloggs",
"status": "Active",
"email": "test#example.com",
"country": {
"code": "AU",
"name": "Australia"
},
"settings": "0",
"_links": {
"self": {
"href": "http://api.mydomain.local/users/1"
}
}
}
Note that 'country' is not in an _embedded field. If it is supposed to be in _embedded, I would have thought that Apigility would automatically do that (since it automatically adds the _links object).
As a related issue, how do I go about returning other rel links, such as back, forward, etc?
The easiest way to get Apigility to render embedded resources is when there is an API/resource associated to the embedded object. What I mean for your example is that you'd have an API resource that has a country entity. In that case, if your getArrayCopy returned the the CountryEntity, Apigility would render it automatically as an embedded resource.
If your getArrayCopy is returning country as an array with code and name, you'll end up with what you saw.
For the other part, the rel links for first, last, prev and next will come from the fetchAll method when you return a Paginator. Your collection extends from this already, but it needs an adapter. The code could look something like this:
public function fetchAll($params)
{
// Return a \Zend\Db\Select object that will retrieve the
// stuff you want from the database
$select = $this->service->fetchAll($params);
$entityClass = $this->getEntityClass();
$entity = new $entityClass();
$hydrator = new \Zend\Stdlib\ArraySerializable();
$prototype = new \Zend\Db\ResultSet\HydratingResultSet($hydrator, $entity);
$paginator = new \Zend\Paginator\Adapter\DbSelect($select, $this->sql, $prototype);
$collectionClass = $this->getCollectionClass();
return new $collectionClass($paginator);
}
There are other paginator adapters as well - an ArrayAdapter which will take in an array of however big and then paginate it so you only get the desired number of results. The downside to this if you use it with database results, you'll potentially be retrieving and discarding a lot of results. The DbSelect paginator will modify the $select object to add the limit and order clause automatically so you only retrieve the bits you need. There are also adapters if you're using DbTableGateway, Iterators or even callbacks. You can also implement your own of course.
Hope this helps. If you have more specific needs or clarification, please comment and I'll do my best.
I posted this example on github.
https://github.com/martins-smb/apigility-renderCollection-example
Hope this helps.

What exactly is "data" that is passed to responses?

I'm writing a custom response that takes data as an input, and I am finding strange properties being added, namely:
add: [Function: add],
remove: [Function: remove]
When I log out some example data, I get:
[ { books:
[ { id: 1,
title: 'A Game of Thrones',
createdAt: '2015-08-04T04:53:38.043Z',
updatedAt: '2015-08-04T04:53:38.080Z',
author: 1 } ],
id: 1,
name: 'George R. R. Martin',
createdAt: '2015-08-04T04:53:38.040Z',
updatedAt: '2015-08-04T04:53:38.073Z' },
{ books:
[ { id: 2,
title: 'Ender\'s Game',
createdAt: '2015-08-04T04:53:38.043Z',
updatedAt: '2015-08-04T04:53:38.080Z',
author: 2 },
{ id: 3,
title: 'Speaker for the Dead',
createdAt: '2015-08-04T04:53:38.043Z',
updatedAt: '2015-08-04T04:53:38.081Z',
author: 2 } ],
id: 2,
name: 'Orson Scott Card',
createdAt: '2015-08-04T04:53:38.042Z',
updatedAt: '2015-08-04T04:53:38.074Z' } ]
Which looks innocent enough, but results in the strange add and remove functions when I use a custom serializer on it. If I take this data and hard-code it straight into the serializer, those are not present. Apparently something is lurking inside of data that's not being printed to the console.
So, what is data?
Edit: So, I'm still not quite sure what other magical properties live in here, but:
Object.keys(data[0].books))
reveals
[ '0', 'add', 'remove' ]
Which is where those are coming from. Why is this included in the data passed to custom responses? And what else might be hiding in there...
More importantly, how do I strip this gunk out and make data a normal object?
JSON.parse(JSON.stringify(data));
That cleans it up nicely, though it feels like a hack. (Actually, it's definitely a hack.)
I assume your data attribute is returned by a database query. e.g.:
Model.find(...).exec(function (err, data) { ... });
But what are these .add() and .remove() methods?
Here is what you can find in the docs:
For the most part, records are just plain old JavaScript objects (aka POJOs). However they do have a few protected (non-enumerable) methods for formatting their wrapped data, as well as a special method (.save()) for persisting programmatic changes to the database.
We can go deeper:
"collection" associations, on the other hand, do have a couple of special (non-enumerable) methods for associating and disassociating linked records. However, .save() must still be called on the original record in order for changes to be persisted to the database.
orders[1].buyers.add({ name: 'Jon Snow' });
orders[1].save(function (err) { ... });
So these methods (.add(), .remove(), .save()) are useful if you play with "collection" associations.
How to remove them?
You'll need to use .toObject() which returns a cloned model instance stripped of all instance methods.
You might want to use .toJSON() that also returns a cloned model instance. This one however includes all instance methods.

Multiple entry select2 and angular model fetched by $resource

I am having some difficulty figuring out how to make it all work together. Here is what I would like to do:
The model is fetched using $resource from the rest API:
var itemResource = $resource('http://blabla.com/items/:id');
$scope.item = itemResource.get({id: '12345'});
The returned item has some fields among which is one array field that lists the ids of the categories:
{
"item_name: "some value",
"categories": ["cat_id1", "cat_id7", "cat_id8"]
}
In the UI I want these categories to be shown as editable multi select. The user should not operate using ids, but rather he should see and be able to chose string representations which come from the mapping within the application. So in html:
<input type"text" ui-select2="categoryOptions" ng-model="item.categories" />
and also in controller:
var categoryMapping = [
{id: "cat_id1", text: "CategoryAlpha"},
...
{id: "cat_id8", text: "CategoryOmega"},
...
];
$scope.categoryOptions = {
'multiple': true,
'placeholder': 'Chose categories',
'width': 'element',
'data': categoryMapping,
};
Obviously the pieces of code above are not working and I don't know how to make them work to do what I want. ui-select2 wants the model (item.categories) to be an array of objects {id, text} and I want it to store only the ids in the items in the database and have the mapping separate. I can't be the first one to do it, there must be a solution, please help.
Thanks

Update values in array in MongoDB

I'm trying to come up with a way to update the values in an array of objects in mongo. I have a collection which looks like
[
{ CourseName: '',
Sessions: [
{
_id: null, //oops I didn't set this in the import
Name: 'blah',
Location: 'moon'
}]
}
]
Now I need to set the _id field. I tried the documented approach of doing
db.Course.update({'Sessions._id': null}, {$set:{'Sessions.$._id': ObjectId()}}, false, true)
But I ran into this bug http://jira.mongodb.org/browse/SERVER-1055 which meant that I couldn't do it. Is there some syntax which will allow me just to itterate over the collection and update each record by hand? I tried a few things like
db.Course.find().forEach(
function(course)
{
course.Sessions.forEach(function(session)
{
session._id=ObjectId();
course.Save(session); //Don't know how to save a single object
});
});
but they didn't work. I'm looking for some way to just update that value in each session.
I think what you want is:
db.Course.find().forEach(
function(course)
{
course.Sessions.forEach(function(session)
{
session._id=ObjectId();
});
db.Course.save(course);
});
However, you can run into problems saving stuff into a collection you're in the middle of iterating over, so I'd suggest loading a bunch of documents into an array, processing them, loading another batch, etc.