How to get properties of nested objects with ng-multiselect-dropdown - javascript

I'm trying to use the ng-multiselect-dropdown https://www.npmjs.com/package/ng-multiselect-dropdown. I've got an array, that contains nested objects. The structure looks some kind like this:
obj1: {
id: string;
atr1: {
atr2: string;
atr3: string;
}
}
My question:
How can I display for example atr2 in the dropdown-menu? This is my dropdown-setting:
dropdownSettingsProjectManagers: any = {
singleSelection: false,
idField: 'id',
textField: 'atr1.atr2', //? What do I have to put in here?
showSelectedItemsAtTop: true,
clearSearchFilter: true,
allowSearchFilter: true,
enableCheckAll: false,
allowRemoteDataSearch: true
};
Thanks, for every help.

Related

dynamicly nested object from another object

trying to figure out how to dynamicly create a new nested object from this one:
object1 = {
DataStore : false,
Header: false,
Footer : false,
Sidebar : false,
Main : false,
}
to nested one like this:
const registerComponentsLocal = {
'DataStore': {
'debug': false
},
'Header': {
'debug': false
},
'Footer': {
'debug': false
},
'Sidebar': {
'debug': false
},
'Main': {
'debug': false
},
}
keys and values have to by dynamic. Only important thing is a structure of the final object.
Any ideas would be greatly appricieated.
To create a new instance (i.e preserve the old one)
let originalObject = {
DataStore : false,
Header: false,
Footer : false,
Sidebar : false,
Main : false,
}
let newObject = Object.assign({}, originalObject) // Copies the original object
Object.entries(newObject).forEach(([key, value]) => newObject[key] = {debug: value})
Here's a method using reduce
Object.entries(object1)
.reduce((b,a) => ({...b, [a[0]] : {debug:a[1]}}), {})
To iterate, we need an array and Object.entries gives us that. Then, using reduce, we iterate through each item in object1, and build a result. Here, this line ({...b, [a[0]] : {debug:a[1]}}) takes our accumulating object b and adds in the next iterable: {key: { debug: value}}`
let object1 = {
DataStore : false,
Header: false,
Footer : false,
Sidebar : false,
Main : false,
}
const registerComponentsLocal = Object.entries(object1).reduce((b,a) => ( {...b, [a[0]] : { debug:a[1]} }),{})
console.log(registerComponentsLocal)

Dynamic lookup from React's state in material-table

I'm using the material-table component, which I fill with dynamic data coming from Redux (an array of objects), but then I do other things with that data inside my component's state. To create column dropdown filters, there's an element inside each column's array of options, lookup, that receives an object and creates the dropdown based on it's values.
I am extracting some items from my data and putting them inside an element in my component's state. This is an object, the same kind that lookup receives. The thing is that the component shows an empty dropdown, as if the object was empty, but it's not. I'm logging it in into the console and the object is filled with the data I need.
I initially thought it was a render problem, that the object is empty at the beggining, and then it's filled with data, but the component renders every time.(Yeah, React is reactive).
This is only the code needed to help me solve this problem:
Table component
import React, { Component } from "react";
import MaterialTable from "material-table";
class CustomTable extends Component {
state = {
column1: "",
column2: "",
column3: "",
column1FilterList: {}
columns: [
{
title: "Column1",
field: "column1",
editable: "onAdd",
filtering: true,
lookup: { ...this.column1FilterList }
},
{
title: "Column2",
field: "column2",
editable: "onAdd",
filtering: true,
},
{
title: "Column3",
field: "column3",
editable: "onAdd",
filtering: true
}
]
};
componentDidMount() {
this.props.fetchValues()
this.props.fetchApplications()
this.filterColumn1ExistingKeys()
}
filterColumn1ExistingKeys = () => {
return this.props.elements.map(element => {
return this.setState(prevState => ({
column1FilterList: {
...prevState.column1FilterList,
[element.name]: element.name
}
}))
})
}
render() {
return (
<div>
<MaterialTable
options={{
search: false,
actionsColumnIndex: 4,
filtering: true
}}
title="Search by"
columns={this.state.columns}
data={this.state.data}
/>
</div>
);
}
}
export default CustomTable;
The problem is how you save that data. You create a new object in the constructor with { ...this.column1FilterList }. This will create a new object which will act as the lookup object, which is filled with the initial data of column1FilterList (empty). Updating the column1FilterList later does not change that lookup object, because it is disconnected (new object). You have to update the lookup within the columns as well like this:
const filterColumn1ExistingKeys = () => {
const column1FilterList = this.state.column1FilterList;
this.props.elements.forEach(element => column1FilterList[element.name] = element.name)
this.setState({
column1FilterList,
columns: [{
title: "Column1",
field: "column1",
editable: "onAdd",
filtering: true,
lookup: { ...column1FilterList }
},
{
title: "Column2",
field: "column2",
editable: "onAdd",
filtering: true,
},
{
title: "Column3",
field: "column3",
editable: "onAdd",
filtering: true
}
]
})
}
Hope this helps. Let me know, if that works for you. If you have any questions, let me know. Happy coding.

How do I hide certain rows in a ui-grid based on its values?

I have a simple UI grid with these options:
$scope.transactionGrid = {
enableSorting : true,
enableColumnResize : true,
enableScrollbars : true,
enablePaginationControls : false,
minRowsToShow : 6,
onRegisterApi : function(gridApi) {
$scope.gridEventsApi = gridApi;
}
};
I want to hide rows which have a specific value, deleted: "y".
$scope.transactionGrid.data = [
{ Name: "First", deleted: "y" },
{ Name: "Second", deleted: "y" },
{ Name: "Third", deleted: "n" },
{ Name: "Fourth", deleted: "n" }
];
Without actually changing the data, can it be filtered out from rows?
One way is to adjust the row-repeater-template to check for some row-specific value and make the row show/hide that way.
I created a Plunkr showcasing a possible solution.
First you need to create your row-value-checker-function:
appScopeProvider: {
showRow: function(row) {
return row.deleted !== 'y';
}
},
Then you adjust their template by adding that check to their row-repeater
$templateCache.put('ui-grid/uiGridViewport',
...
ng-if=\"grid.appScope.showRow(row.entity)\"
...
}
I know you specifically said "without actually changing the data", but assigning a filtered dataset to the grid would not change the dataset, just the data for the grid. Also it might be a relevant and valid solution for other cases like this.
I forked CMR's Plunk to demonstrate this: http://plnkr.co/edit/NntwWb?p=preview
The key part is just adding a filter when assigning the dataset:
$scope.gridOptions = {
data: $scope.myData.filter(function(row) {
return row.deleted !== "y";
})
};
You can hide it by creating cell templates and hide it based on row value for every field:
$scope.transactionGrid = {
enableSorting : true,
enableColumnResize : true,
enableScrollbars : true,
enablePaginationControls : false,
minRowsToShow : 6,
onRegisterApi : function(gridApi) {
$scope.gridEventsApi = gridApi;
}
// Column template definitions:
columnDefs: [
{
name: 'Name',
displayName: 'Name',
cellTemplate : '<div ng-if="row.entity.deleted">{{row.entity.Name}}</div>'
}
]
};
I made a Plunk to demonstrate a viable technique to solve this: https://plnkr.co/edit/XQRC45vaiZCySZYkEGrz?p=preview

Angular using filter to Update?

I wanted to update my model using $filter or some other smart way without having to do multiple for each.
So basically I have my model similar to below:
$scope.projects = [
{
tasks: [
{
name: 'task name',
visible: true,
starred: true
}
],
createdAt: 'something'
},
{
tasks: [
{
name: 'second task name',
visible: true,
starred: false
}
],
createdAt: 'something'
}
]
What I wanted to do is by using $filter or some other way like underscore and so on, to update the content of the variable. So for instance, when I click a button, I'd like to set visible = true only to tasks that are starred.
Anyone have a suggestion on how to achieve that? Is it possible or I would have to do a couple of loops?
Something like:
$filter('filter')($scope.projects, {{starred = true}}).tasks.visible = true
UPDATE
With the help from #jbrown I was able to achieve what I wanted.
Just in case someone needs similar approach, the final solution was as written below:
_.forEach($scope.projectsModel.projects, function(proj){
_.forEach(_.filter(proj.tasks, {starred: true}), function(task){
task.visible = true;
});
});
Using underscore you can use a combination of filter and find to get the results you are looking for.
$scope.filteredProjects = _.filter($scope.projects, function(proj) {
return _.find(proj.tasks, {
visible: true, starred: true });
});

How to initialize object properly and start from clean slate?

I've got this class:
Ext.define('Customer_Portal_UI.FormParameters', {
constructor: function (c) {
Ext.each(this.ParticipantFormParameters, function (field) {
if (field.toFieldSet != null) {
var fieldSetName = c.targetFieldSetPrefix + field.toFieldSet;
field.toFieldSet = fieldSetName;
}
});
},
ParticipantFormParameters: [
{ name: 'service_executive_account_Number', visible: false },
{ name: 'firstname', visible: true, displayText: 'Firstname', toFieldSet: 'GeneralInfoFS', allowBlank: false },
{ name: 'lastname', visible: true, displayText: 'Lastname', toFieldSet: 'GeneralInfoFS', allowBlank: false },
{ name: 'gendercode', visible: true, hasCheckbox: true, displayText: 'Gender', toFieldSet: 'GeneralInfoFS', xtype: 'combo', allowBlank: false },
]
});
If I do this once:
var formParams = Ext.create(Customer_Portal_UI.FormParameters, { targetFieldSetPrefix: 'add' });
console.log(formParams.ParticipantFormParameters[0].toFieldSet);
I will get addGeneralInfoFS.
But if I create this object many times, I'll get addGeneralInfoFS, addaddGeneralInfoFS, addaddaddGeneralInfoFS
What is going on here ? I tried delete formParams but when I initialize an object if the same type again, same problem.
Is it ExtJS or a javascript problem ? I find it weird I need to put effort into simply destroying objects...
EDIT: Ah! I found this in the documentation:
When placing items in the prototype of the prototype, they will be
shared across all instances of the class. Unless you specifically want
to do this, you should only put "primitive" types inside the prototype
definition.
The question now is how to I declare members without them being "in the prototype" ? That's nice, but where does ParticipantFormParameters go exactly then ? I don't want it in the config cause it's dirty, I'll have to drag this huge (the real code has much more items in the array) block of javascript markup everytime I initialize the object ?
I've refactored things in my application with this approach and I'm completely paralized until this works...I cannot unrefactor...
Thank you.
Why do you modify the property ? Use two different variables. This could be the solution :
(...)
Ext.each(this.ParticipantFormParameters, function (field) {
if (field.toFieldSet != null) {
var fieldSetName = c.targetFieldSetPrefix + field.toFieldSetRaw;
field.toFieldSet = fieldSetName;
}
});
},
ParticipantFormParameters: [
{ name: 'service_executive_account_Number', visible: false },
{ name: 'firstname', visible: true, displayText: 'Firstname', toFieldSetRaw: 'GeneralInfoFS', allowBlank: false },

Categories

Resources