Do I need to execute a bind(this) somewhere and the console log placement seems to be off?
var company = {
employees: [{
name: "doug"
},
{
name: "AJ"
}
],
getName: function(employee) {
return employee.name
},
getNames: function() {
return this.employees.map(this.getName)
},
delayedGetNames: function() {
setTimeout(this.getNames, 500)
}
}
console.log(company.delayedGetNames());
setTimeout(this.getNames.bind(this), 500)
^
|
+----< HERE
var company = {
employees: [{
name: "doug"
},
{
name: "AJ"
}
],
getName: function(employee) {
return employee.name
},
getNames: function() {
return this.employees.map(this.getName)
},
delayedGetNames: function() {
var fn = function() {
var names = this.getNames();
console.log(names);
};
setTimeout(fn.bind(this), 500);
}
}
company.delayedGetNames();
Related
I need to call transformResponse many times based persons array. But the following code call only the last index
function fill() {
var persons = [
{ id: 34, text: $translate.instant("enter") },
{ id: 36, text: $translate.instant("high") },
{ id: 53, text: $translate.instant("graduates") },
{ id: 35, text: $translate.instant("persons") },
]
var personSubCategoriesList = [];
for (var i = 0; i < persons.length; i++) {
$scope.remote = {
url: window.config.apiHostUrl + `lookup/Get?id=${persons[i].id}`,
transformResponse: function (data) {
var personSubCategories = angular.fromJson(data);
angular.forEach(personSubCategories, function (personSubCategoriesObjet) {
var categories = { name: personSubCategoriesObjet.localizedName, code: personSubCategoriesObjet.id };
personSubCategoriesList.push(categories);
});
return personSubCategoriesList.map(function (adminCategories) {
return {
name: adminCategories.name,
code: adminCategories.code
};
});
}
};
}
}
I found the solution by using observable $q
In the code below, I am trying to run onChange={this.handleChange} with react js.I would like to obtain the items by filtering them based on what is written on Input,I tried the following :
<input value={this.state.name} onChange={this.handleChange}/>
handleChange= evt =>
this.setState(
{
name: evt.target.value.toLowerCase()
},
() => {
.
.
.
}
)
Firstly there is an input and the its function that return the value of the input.
const data=[
{ "info": [{ "name": "ali" }, { "name": "amir" }, { "name": "maya" }] },
{ "info": [{ "name": "eli" }, { "name": "mary" }] },
{ "info": [{ "name": "ali" }] },
{
"info": [{ "name": "emila" }, { "name": "alex" }, { "name": "sosan" }]
}
]
data = data .filter(item => {
if (this.renderName(item).some((r) => {
r.includes(name)
}
)) return item;
})
renderName(element){
let elementAdd = []
for (let i = 1; i < element.info.length; i++) {
elementAdd.push(element.info[i].name.toLowerCase())
}
return elementAdd
}
And I want to filter the data array based on input value, but it does not work!
Edit:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [
{ id: 1, info: [{ name: "ali" }, { name: "amir" }, { name: "maya" }] },
{ id: 2, info: [{ name: "eli" }, { name: "mary" }] },
{ id: 3, info: [{ name: "mary" }] },
{
id: 4,
info: [{ name: "emila" }, { name: "alex" }, { name: "sosan" }],
},
],
name: "",
};
}
reorganiseLibrary = () => {
const { name } = this.state;
let library = data;
if (name !== "") {
library = library.filter((item) => {
if (
this.renderName(item).some((r) => {
name.includes(r);
})
)
return item;
});
}
};
renderName(element) {
let elementAdd = [];
for (let i = 1; i < element.info.length; i++) {
elementAdd.push(element.info[i].name.toLowerCase());
}
return elementAdd;
}
handleChange = (evt) =>
this.setState(
{
name: evt.target.value.toLowerCase(),
},
() => {
this.reorganiseLibrary();
}
);
renderLibrary = () => {
const { library } = this.state;
if (!library || (library && library.length === 0)) {
return "";
}
return library.map((item) => <div className="item">{item.id}</div>);
};
render() {
return (
<div>
<input value={this.state.name} onChange={this.handleChange} />
{this.renderLibrary()}
</div>
);
}
}
ReactDOM.render(<App></App>, document.getElementById("app"));
There are many issues in your code and I will only discuss the critical points.
reorganiseLibrary method
data not extracted from props
handleChange method
wrong use of setState. No second parameter as far as I know.
renderName method
you only get name property but you expect an object in renderLibrary method
Here is a solution that I can think of.
state = {
data: [],
name: "",
library: [] // use this to show latest filtered data
}
function onChange(event) {
const { data} = this.state;
this.setState(
{
name: event.target.value.toLowerCase()
});
let filteredResult = [];
for(var index = 0; index < data.length; index++) {
var filteredValue = data[index].info.filter(item => item.name.includes(event.target.value));
if(filteredValue.length != 0)
filteredResult.push(filteredValue);
}
if(filteredResult.length != 0) // remove this if you want to reset the display in your UI
setState({library : filteredResult});
}
renderLibrary = () => {
const { library } = this.state;
if (library.length > 0)) {
return library.foreach(item => (<div className="item">{item.id}</div>)); // modify the onChange filter if you want the outer object
};
I'm trying to add a new Observable to an ObservableArray which has been mapped initially with KO's mapping plugin. But I don't get that working. Firebug is telling me "TypeError: totalChf is not a function". Looking at the added Observable, I notice that the Computed functions were not created. I've tried several methods, still without success... What am I missing?
Thanks in advance
Here the code:
var vm;
var ClientsMapping = {
create: function (options) {
var client = ko.mapping.fromJS(options.data, ContainersMapping)
//Some computed observables for level one here...
return client;
}
}
var ContainersMapping = {
'Containers': {
create: function (options) {
var container = ko.mapping.fromJS(options.data, MoneyAccountsMapping)
container.totalChf = ko.computed(function () {
var total = 0;
$.each(container.MoneyAccounts(), function () {
if (this.Currency() == "CHF") {
total += this.Amount();
}
})
return total;
})
//Some computed observables for level two here...
return container;
}
}
}
var MoneyAccountsMapping = {
'MoneyAccounts': {
create: function (options) {
var macc = new MoneyAccountModel(options.data)
//Some computed observables for level three here...
return macc;
}
}
}
var ClientModel = function (data) {
ko.mapping.fromJS(data, {}, this);
}
var ContainerModel = function (data) {
ko.mapping.fromJS(data, {}, this);
}
var MoneyAccountModel = function (data) {
ko.mapping.fromJS(data, {}, this);
}
var data = [
{
'Clients': 'Thomas',
'Containers': [
{
'ContName': 'Cont01',
'MoneyAccounts': [
{ Currency: "CHF", Amount: 1000 },
]
}
]
},
{
'Clients': 'Ann',
'Containers': [
{
'ContName': 'Cont01',
'MoneyAccounts': [
{ Currency: 'CHF', Amount: 1000 },
{ Currency: 'EUR', Amount: 500 }
]
}
]
}
]
function viewModel() {
var self = this;
self.clients = ko.observableArray()
self.clientsCount = ko.computed(function () {
return self.clients().length
})
}
$(function () {
vm = new viewModel();
vm.clients(ko.mapping.fromJS(data, ClientsMapping)());
var cont1 = {
'ContName': 'ContXX',
'MoneyAccounts': [
{ Currency: "XXX", Amount: 1000 },
]
};
var cont2 = {
'ContName': 'ContYY',
'MoneyAccounts': [
{ Currency: "YYY", Amount: 1000 },
]
};
var cont3 = {
'ContName': 'ContZZ',
'MoneyAccounts': [
{ Currency: "ZZZ", Amount: 1000 },
]
};
var cont4 = {
'ContName': 'ContWW',
'MoneyAccounts': [
{ Currency: "WWW", Amount: 1000 },
]
};
vm.clients()[0].Containers.push(ko.mapping.fromJS(cont1, ContainersMapping));//Attempt1
vm.clients()[0].Containers.push(ko.mapping.fromJS(cont2));//Attempt2
vm.clients()[0].Containers.push(new ContainerModel(cont3));//Attempt3
vm.clients()[0].Containers.push(ko.mapping.fromJS([cont4], ContainersMapping)()[0]);//Attempt4
//...still no success.
})
You will generally want to keep your mappings independent of one another. A good way to do that is to define and perform the mappings within each class:
var ClientModel = function(data) {
var mapping = {
'Containers': {
create: function(options) {
var container = new ContainerModel(options.data)
//Some computed observables for level two here...
return container;
}
}
}
ko.mapping.fromJS(data, mapping, this);
}
Once this is organized, you have a couple options for adding a new item to the observableArray:
Create the new item and push it to the array:
vm.clients()[0].Containers.push(new ContainerModel(cont1))
Specify a key option in your mapping:
var mapping = {
'Containers': {
key: function(item) {
return ko.unwrap(item.ContName);
},
create: function(options) {
var container = new ContainerModel(options.data)
//Some computed observables for level two here...
return container;
}
}
}
Then use mappedCreate to add the item:
vm.clients()[0].Containers.mappedCreate(cont1);
JSFiddle
I have this array:
var itemList = [
{
image: "images/home.jpg",
name: "Home"
},
{
name: "Elvis",
},
{
name: "Jonh"
},
{
image: "images/noah.jpg",
name: "Noah"
},
{
name: "Turtle"
}
]
How can I organize the array to objects with image property come first, so that it looks like this?:
var itemList = [
{
image: "images/home.jpg",
name: "Home"
},
{
image: "images/noah.jpg",
name: "Noah"
},
{
name: "Elvis",
},
{
name: "Jonh"
},
{
name: "Turtle"
}
]
This code put at the beginning elements that have the property 'image'. Other elements stay in the same order.
function compare(a,b) {
if ('image' in a) {
return 1;
} else if ('image' in b) {
return -1;
} else {
return 0;
}
}
itemList.sort(compare);
Try this:
function compare(a,b) {
if (a.image && b.image)
return 0;
if (a.image)
return 1;
return -1;
}
objs.sort(compare);
A bit late, but an alternative:
itemList.sort(function(e1,e2){ return (e1.image === undefined) - (e2.image === undefined); });
I'm trying to turn this:
[ { '231634908': 137875 },
{ '388252786': 150004 },
{ '333624027': 144107 },
{ '382758108': 149729 },
{ '384113458': 149803 },
{ '384844004': 149848 },
{ '405877005': 150481 },
{ '405877005': 150481 } ]
Into this:
{
'231634908': 137875,
'388252786': 150004,
'333624027': 144107,
'382758108': 149729,
'384113458': 149803,
'384844004': 149848,
'405877005': 150481,
'405877005': 150481
}
Using underscore.
I tried
_.object(list);
_.object(_.keys(list), _.values(list));
_.object(_.keys(list[0]), _.values(list[0]));
I'm no expert on underscore.js, but try this:
_.extend.apply(null, list);
One caveat: this will actually modify the first element of the list. If this is a concern you might want to use something like this instead:
_.extend.apply(null, [{}].concat(list));
You want _.reduce():
_.reduce(list, function(memo, o) {
var k = Object.keys(o)[0];
memo[k] = o[k];
return memo;
}, {});
A more elegant and native way to do it.
var a = [ { '231634908': 137875 },
{ '388252786': 150004 },
{ '333624027': 144107 },
{ '382758108': 149729 },
{ '384113458': 149803 },
{ '384844004': 149848 },
{ '405877005': 150481 },
{ '405877005': 150481 } ];
var b = {};
Array.prototype.forEach.call(a,function(elem) {
var keys = Object.keys(elem);
b[keys[0]] = elem[keys[0]];
});
One more native solution for case with multiple fields per object
var objects = [ { '231634908': 137875 },
{ '388252786': 150004 },
{ '333624027': 144107 },
{ '382758108': 149729 },
{ '384113458': 149803 },
{ '384844004': 149848 },
{ '405877005': 150481 },
{ '405877005': 150481 } ]
var singleObject = {};
for(var i in objects){
var oKeys = Object.keys(objects[i]);
for(var j in oKeys){
singleObject[oKeys[j]] = objects[i][oKeys[j]];
}
}
console.log(singleObject);
I know this is really old, but it inspired me to do this natively one-line for multi key objects:
var arrayOfObjectsToCombine = [ { foo: 'bar', dog: 'cat' }, { baz: 'boom' } ];
arrayOfObjectsToCombine.reduce(function(done, obj) { Object.keys(obj).map( function(K) { done[K] = obj[K] } ); return done; }, {})
result:
{ foo: 'bar', dog: 'cat', baz: 'boom' }
You could use Object.assign() and spread syntax like this:
let array = [ { '231634908': 137875 },
{ '388252786': 150004 },
{ '333624027': 144107 },
{ '382758108': 149729 },
{ '384113458': 149803 },
{ '384844004': 149848 },
{ '405877005': 150481 },
{ '405877005': 150481 } ]
const output = Object.assign({}, ...array)
console.log(output)