For some reason I need to create headers dynamically because of component I used.
So I have a function which and that function I want to use to provide values to columnDefs
ctrl.getColumnDefs = () => {
let columns = []
if (name === 'deamon') {
var normalCol = {
field: 'name',
enableSorting: true,
cellTooltip: (row, col) => row.entity[col.field],
enableCellEdit: false
};
return columns.push(normalCol);
}
Then I am using
ctrl.grid = {
columnDefs: getColumnDefs()
}
Which is throwing TypeError: self.options.columnDefs.forEach is not a function
You are returning the value of push. That returns the new length of the array as per docs here.
You probably want to return columns instead of push.
Probably you want this
columns.push(normalCol)
return columns
Related
I am trying to create parts of tables many times but with different arguments. To do so, I have created a new function that takes a parameter, which is then used in a function in the table. My IDE shows the use of the parameter value inside the function as an "Up-value" problem.
Is there any way I can achieve this functionality without that issue?
function createTable(value)
myTable = {
name = 'Table',
args = {
time = 0,
score = {
function()
return value / 2
end
},
},
}
return myTable
end
Using MySQL.
I have the following entity:
import { Column, Entity, ValueTransformer } from 'typeorm';
const ormIdTransformer: ValueTransformer = {
to: (value: any) => (value !== undefined && value !== null ? Number(value) : value),
from: (value: any) => (value !== undefined && value !== null ? String(value) : undefined),
};
#Entity()
export class User {
#Column({ type: 'int', transform: ormIdTransformer, primary: true })
id: string;
#Column({ type: 'int', transform: ormIdTransformer })
profileId: string;
// ...
}
Please note that profileId is not mapped as a relation here.
In my app, I have a custom UserRepository, and it has access to an entityManager (both internally, and externally, in case the operation is running inside a transaction).
I'm trying to search for all users that have specific IDs and a specific profile (also by ID):
// Just an example
const profileId = '1';
const userIds = ['1', '2', '3', /* ... */];
const ids = await entityManager.find(User, { where: { profileId, id: In(userIds) }, select: ['id'] });
I'd expect TypeORM to generate a query similar to the following:
SELECT `User`.`id` from `User` `User` WHERE `User`.`profileId` = ? AND `User`.`id` IN ?`
-- Parameters: [1, [1, 2, 3, ...]]
Instead, TypeORM seems to completely ignore the FindOperator (the In) I provided, and just passes In(userIds) through as if it was a normal value. This FindOperator goes directly to my ValueTransformer, which I think is not correct.
But that's not the worse of it. By activating query logging, I see that TypeORM generates the following query:
SELECT `User`.`id` AS `User_id` FROM `User` `User` WHERE `User`.`profileId` = ? AND `User`.`id` = ?
-- Parameters: [2, NaN]
The operation obviously fails with a database error: QueryFailedError: ER_BAD_FIELD_ERROR: Unknown column 'NaN' in 'where clause'.
Notice how the condition for the id column is not being applied correctly: it should be IN, not =.
Am I doing something wrong?
After some debugging, I found out that the problem was related to the custom transformer I was implementing for my IDs.
QueryBuilder has special logic to take care of FindOperator, but that only works if ColumnMetadata.getEntityValue (which is called in QueryBuilder) actually returns an operator. But ColumnMetadata.getEntityValue lacks the logic to deal with FindOperator; instead of applying the transformation to the operator's wrapped value, it applies the transformation to the operator itself.
With that knowledge, I looked up for problems related to FindOperator and custom transformations, and found an answer to a similar question. That helped me implement a transformation process that actually works with FindOperators.
Long story short, turns out I had to reconstruct the entire operator, and transform the values wrapped in it myself. This is what I came up with:
import { FindOperator, FindOperatorType, ValueTransformer } from 'typeorm';
const idFromDb = (value: any) => {
if (value === undefined || value === null) {
return undefined;
}
return String(value);
};
const idToDb = (value: any) => {
if (value === undefined || value === null) {
return undefined;
}
if (Array.isArray(value)) {
return value.map(idToDb);
}
if (value instanceof FindOperator) {
return new FindOperator(
value.type as FindOperatorType,
idToDb(value.value),
value.useParameter,
value.multipleParameters,
);
}
return Number(value);
};
export const ormIdTransformer: ValueTransformer = {
to: idToDb,
from: idFromDb,
};
I'm using angular ui-grid (no ng-grid) and want to pass a function to calculate a column's total value. In the documentation they explicitly say it is possible; it is just that I canĀ“t find how to do it.
This is how I'm showing a total (sum) for another columns:
aggregationType: uiGridConstants.aggregationTypes.sum,
aggregationHideLabel: true,
footerCellFilter: 'currencyFilter',
footerCellClass: 'ui-grid-centerCell'
Now, instead of using uiGridConstants.aggregationTypes.sum, I want to pass a function to calculate the value.
Many thanks and bye ...
My Idea is to Create a method in your Controller like
$scope.sum = function(row){
var sum1 = row.entity.sum1 + row.entity.sum2;
console.log('Sum of Value is = ',sum1);
}
Note : sum1 and sum2 is columnDefs of Field value like
$scope.gridsOptions = {
columnDefs : [
{
field : 'sum1',
name :'xx'
},
{
field : 'sum2',
name : 'xxx'
}
]}
You can also solve this by adding custom tree aggregation.
treeCustomAggregations: {
sum: {
aggregationFn: stats.aggregator.sumSquareErr, finalizerFn: function (aggregation) {
//Do rest of your calculations here
var total = $scope.gridApi.grid.columns[column_number].getAggregationValue() ;
aggregation.value = total ;
aggregation.rendered = (aggregation.value).toFixed(1);
}
Or you can refer this question for custom aggregate template and calling your custom function from it.
I have an array in state, let's say this.state.arr.
I want to add something to this state property, and then change some more properties.
Option 1
onChange(event){
this.state.arr.push('newvalue');
...
this.setState({some:'val',arr:this.state.arr})
}
Option 2
onChange(event){
var newArr = this.state.arr;
...
newArr.push('newvalue');
...
this.setState({some:'val',arr:newArr})
}
So.. I know this.state is supposed to be treated immutable. But is it ok to use it like in option 1 where I still set the state from it, or do I need to go with something like option 2, and thus always first making a copy in memory
For now, this is the best way.
this.setState(previousState => ({
myArray: [...previousState.myArray, 'new value']
}));
Both of the options you provided are the same. Both of them will still point to the same object in memory and have the same array values. You should treat the state object as immutable as you said, however you need to re-create the array so its pointing to a new object, set the new item, then reset the state. Example:
onChange(event){
var newArray = this.state.arr.slice();
newArray.push("new value");
this.setState({arr:newArray})
}
Another simple way using concat:
this.setState({
arr: this.state.arr.concat('new value')
})
If you are using ES6 syntax you can use the spread operator to add new items to an existing array as a one liner.
// Append an array
const newArr = [1,2,3,4]
this.setState(prevState => ({
arr: [...prevState.arr, ...newArr]
}));
// Append a single item
this.setState(prevState => ({
arr: [...prevState.arr, 'new item']
}));
Short way with useState hook:
const [value, setValue] = useState([])
setValue([...value, newvalue])
the best away now.
this.setState({ myArr: [...this.state.myArr, new_value] })
onChange() {
const { arr } = this.state;
let tempArr = [...arr];
tempArr.push('newvalue');
this.setState({
arr: tempArr
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
For functional components with hooks
const [searches, setSearches] = useState([]);
// Using .concat(), no wrapper function (not recommended)
setSearches(searches.concat(query));
// Using .concat(), wrapper function (recommended)
setSearches(searches => searches.concat(query));
// Spread operator, no wrapper function (not recommended)
setSearches([...searches, query]);
// Spread operator, wrapper function (recommended)
setSearches(searches => [...searches, query]);
source: https://medium.com/javascript-in-plain-english/how-to-add-to-an-array-in-react-state-3d08ddb2e1dc
React hook - useState (2022)
const [array, setArray] = useState([]);
const handleChange = (newValue) => {
setArray((array) => [...array, newValue]);
};
handleValueChange = (value) => {
let myArr= [...this.state.myArr]
myArr.push(value)
this.setState({
myArr
})
This might do the work.
If you want to keep adding a new object to the array i've been using:
_methodName = (para1, para2) => {
this.setState({
arr: this.state.arr.concat({para1, para2})
})
}
This might not directly answer your question but for the sake of those that come with states like the below
state = {
currentstate:[
{
id: 1 ,
firstname: 'zinani',
sex: 'male'
}
]
}
Solution
const new_value = {
id: 2 ,
firstname: 'san',
sex: 'male'
}
Replace the current state with the new value
this.setState({ currentState: [...this.state.currentState, new_array] })
const [array, setArray] = useState([]);
const handleChange = (newValue) => {
setArray((prevState) => [...prevState, newValue]);
};
If the new state is computed using the previous state, you can pass a function to setState. The function will receive the previous value, and return an updated value.
setState doc.
Hello I am trying to write a jasmine test for a backbone view and one of its function. I want to test the correct behavior of the function in the case a user checks a checkbox in the rendered view then submit.
Here is the tests :
describe("buildCI()", function() {
describe("with a category selection allowed's quidget model", function() {
it("returns a CoacheeIssue model with the selected categories", function() {
selection_allowed = true;
lcc_selection_allowed = false;
var view = new Rails3DeviseRspecCucumber.Views.CategoryPicker({
collection: categoriesCollection,
answers: answers,
category_ids: category_ids,
credentials: credentialsCollection,
user_hash: user_hash,
selection_allowed: selection_allowed,
lcc_selection_allowed: lcc_selection_allowed
});
// render the view so we can manipulate its DOM elements
view.render();
elDebug = $(view.$el);
// Check programmatically a category checkbox
$(elDebug.find('input.category-checkbox#5061c6a48624da6f4100000a')[0]).prop('checked', true);
// call the buildCI() function and check the result
result = view.buildCI();
console.log(result);
expect(result.get('categories')).toContain('category one');
expect(result.get('categories')).not.toContain('category two');
})
})
Unfortunately the test fails with this message : Expected [ ] to contain 'category one'.
I know it is not a coding error, because it is working in live, I would just like to know how to test it.
Here is the function :
buildCI: () ->
# prepare the category_ids and categories (names) attributes
if #selection_allowed
selectedCategories = []
for checkbox in $('input.category-checkbox')
checkboxEl = $(checkbox)
if checkbox.checked
selectedCategories.push(_.find(#collection.models, (model) ->
model.id == checkboxEl.attr('id')
))
category_names = _.map(selectedCategories, (category) -> category.get('name'))
category_ids = _.map(selectedCategories, (category) -> category.get('_id'))
else
category_names = _.map(#collection.models, (category) -> category.get('name'))
category_ids = _.map(#collection.models, (category) -> category.get('_id'))
return new Rails3DeviseRspecCucumber.Models.CoacheeIssue({
is_solved: false, status: 'active', solution_value_estimate: '',
answers: #answers, categories: category_names, category_ids: category_ids
})
Thanks in advance
Is your selector too strict? I notice that it is:
$(elDebug.find('input.category-checkbox#5061c6a48624da6f4100000a')[0]).prop('checked', true);
but perhaps you only want it to be just:
$(elDebug.find('input.category-checkbox')[0]).prop('checked', true);