How to add dynamic property in angularjs object - angularjs

I have object
$scope.postData = {
'pmu.messages.message': $scope.upd.message,
'pmu.received.id': $scope.upd.atomByReceivedBy.id,
};
and in scope there is $scope.ImageList which contains image path array
[
{ img: 'a.jpg', smallimg: 'b.jpg', smpath: 'c.jpg' },
{ img: 'a1.jpg', smallimg: 'b1.jpg', smpath: 'c1.jpg' },
];
I want to add these array value to $scope.postData field property value
as
$scope.postData = {
'pmu.messages.message': $scope.upd.message,
'pmu.received.id': $scope.upd.atomByReceivedBy.id,
'pmu.image[0].img':
'pmu.image[0].smallimg':
'pmu.image[0].smimg':
'pmu.image[1].img':
'pmu.image[1].smallimg':
'pmu.image[1].smimg':
}
How to achieve this?

Iterate $scope.ImageList and use Bracket Notation to create properties.
Here in the example, I have used just one property
$scope.ImageList.forEach(function(element, index){
$scope.postData['pmu.image[' + index +'].img'] = element.img;
});

You can iterate the array with Array.forEach, and then extract the key & value of each image using Object.entries.
$scope = {
upd: {
message: '',
atomByReceivedBy: {
id: ''
}
},
ImageList: [{
img: 'a.jpg',
smallimg: 'b.jpg',
smpath: 'c.jpg'
},
{
img: 'a1.jpg',
smallimg: 'b1.jpg',
smpath: 'c1.jpg'
},
]
}
$scope.postData = {
'pmu.messages.message': $scope.upd.message,
'pmu.received.id': $scope.upd.atomByReceivedBy.id,
};
$scope.ImageList.forEach((img, index) => {
Object.entries(img).forEach(([key, value]) => {
$scope.postData[`pmu.image[${index}].${key}`] = value;
});
});
console.log($scope.postData);

Related

loop through objects inside an array in a regex

EDITED
I got an array of objects:
values: [
{ key: "CollinHenderson" },
{ key: "SarahDrasner" },
{ key: "EvanYou" },
{ key: "AdamWathan" }
]
I want to highlight the text if one of them is mentioned ("#..."):
.innerHTML
.replace(
/(?:|^)#[A-Za-z0-9\\-\\.\\__äÄöÖüÜß]+(?:|$)/g,
"<span contenteditable='false' class='markAt'>$&</span>"
);
with this regex (above) everything gets highlighted which starts with a '#'. How could I loop trough my array of objects inside of my regex, so that it only turns out true if one of my users get mentioned. For Example:
"#hello" should be false
"#CollinHenderson" should be true and get therefore highlighted
/(?:|^)#[ //loop through array - if matches a value -> true // ]+(?:|$)/g,
You can pass a function to replace and check in there
const values = [{
key: "CollinHenderson"
},
{
key: "SarahDrasner"
},
{
key: "EvanYou"
},
{
key: "AdamWathan"
}
]
const el = document.getElementById('foo');
el.addEventListener('keyup', e => {
document.getElementById('bar').innerHTML = e.target.value
.replace(
/(?:|^)#[A-Za-z0-9\\-\\.\\__äÄöÖüÜß]+(?:|$)/g,
m => {
if (values.find(v => m.substring(1) === v.key)) return "<span contenteditable='false' class='markAt'>"+ m + "</span>";
return m;
}
);
});
.markAt {
font-weight: 700;
}
<textarea id="foo"></textarea>
<div id="bar">
</div>

Vue.js filtering on array

I am trying to filter an array using a computed property in vue.js. I would like to search on on multiple fields, name, state, tags etc.
My data:
events: [
{
id: 1,
name: 'Name of event',
url: '#',
datetime: '2017-05-10T00:00:00Z',
description: 'The full text of the event',
state: 'VIC',
tags: [
'ordinary',
'advanced'
]
},
{
id: 2,
name: 'Another event',
url: '#',
datetime: '2017-05-12T00:00:00Z',
description: 'The full text of the event',
state: 'VIC',
tags: [
'beginner'
]
},
{
id: 3,
name: 'Great event',
url: '#',
datetime: '2017-05-18T00:00:00Z',
description: 'The full text of the event',
state: 'NSW',
tags: [
'beginner'
]
}
]
},
The following function works as expected, however I cant work out how to have it search the items in 'tags' (commented out).
searchevents: function(){
let result = this.events
if (this.filterValue){
result = result.filter(event =>
event.name.toLowerCase().includes(this.filterValue.toLowerCase()) ||
event.state.toLowerCase().includes(this.filterValue.toLowerCase())
// event.tags.toLowerCase().values().includes(this.filterValue.toLowerCase())
)
}
return result
}
The following returns a blank array, this method works ok when i have done it in angular but not in vue.
searchevents2: function(){
var searchRegex = new RegExp(this.filterValue,'i')
this.events.filter(function(event){
return !self.filterValue || searchRegex.test(event.name) || searchRegex.test(event.state)
})
}
Ideally I would either like to be able to list array items to filter by or just filter by the entire array.
Appreciate any help, first post here so be gentle. I have a lot more experience with Python than Javascript so i may also use incorrect terminology at times.
You weren't too far off.
For your searchEvents filter, you just needed to add the tag filter. Here's how you might do that.
searchevents: function(){
let result = this.events
if (!this.filterValue)
return result
const filterValue = this.filterValue.toLowerCase()
const filter = event =>
event.name.toLowerCase().includes(filterValue) ||
event.state.toLowerCase().includes(filterValue) ||
event.tags.some(tag => tag.toLowerCase().includes(filterValue))
return result.filter(filter)
}
Array.some() is a standard array method that returns true if any element of the array passes your test.
searchevents2: function(){
const searchRegex = new RegExp(this.filterValue,'i')
return this.events.filter(event =>
!this.filterValue || searchRegex.test(event.name) || searchRegex.test(event.state))
}
With searchEvents2 you really only left an errant self in there. Either you needed to set self before you executed the filter, or, as I have done here, turned it into an arrow function.
Example.
const app = new Vue ({
el: '#app',
data: {
search: '',
userList: [
{
id: 1,
name: "Prem"
},
{
id: 1,
name: "Chandu"
},
{
id: 1,
name: "Shravya"
}
]
},
computed: {
filteredAndSorted(){
// function to compare names
function compare(a, b) {
if (a.name < b.name) return -1;
if (a.name > b.name) return 1;
return 0;
}
return this.userList.filter(user => {
return user.name.toLowerCase().includes(this.search.toLowerCase())
}).sort(compare)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.js"></script>
<div id="app">
<div class="search-wrapper">
<input type="text" v-model="search" placeholder="Search title.."/>
<label>Search Users:</label>
</div>
<ul>
<li v-for="user in filteredAndSorted">{{user.name}}</li>
</ul>
</div>

JSON re-grouping with for each method in AngularJs

I am new in angular and i want to re-group a JSON. Is it possible to do with angular.forEach() method?
[
{
"doc":{
"Title":"Main",
"name":"Ajith",
"Day":"03",
"count":3
}
},
{
"doc":{
"Title":"starters",
"name":"Saji",
"Day":"01",
"count":39
}
},
{
"doc":{
"Title":"desert",
"name":"Sajeeb",
"Day":"02",
"count":63
}
},
{
"doc":{
"Title":"Main",
"name":"Suith",
"Day":"03",
"count":3
}
},
{
"doc":{
"Title":"starters",
"name":"Manu",
"Day":"01",
"count":9
}
}
]
I want the output should be like following.
{
"order":[
{
"Day":"01",
"Title":"starters",
"items":[
{
"name":"Saji",
"count":39
},
{
"name":"Manu",
"count":9
}
]
},
{
"Day":"02",
"Title":"desert",
"items":[
{
"name":"Sajeeb",
"count":63
}
]
},
{
"Day":"03",
"Title":"Main",
"items":[
{
"name":"Ajith",
"count":3
},
{
"name":"Suith",
"count":3
}
]
}
]
}
To regroup with angular.forEach() method.
Please help. Thanks.
https://jsfiddle.net/9fwtm0a0/4/
var days = [];
arr.forEach(function(d) {
var day = parseInt(d.doc.Day);
var item = { name: d.doc.name, count: d.doc.count };
if (days[day])
days[day].items.push(item);
else
days[day] = { Day: '0' + day, Title: d.doc.Title, items: item]};
});
days.sort(function (x, y) {
return parseInt(x.Day) > parseInt(y.Day);
});
var eventsinOrder = { order: days };
You don't really need the Angular forEach but you can easily substitute it in:
var days = [];
angular.forEach(arr, function (val, key) {
var day = parseInt(val.doc.Day);
var item = { name: val.doc.name, count: val.doc.count };
if (days[day])
days[day].items.push(item);
else
days[day] = { Day: '0' + day, Title: val.doc.Title, items: [item]};
});
days.sort(function (x, y) {
return parseInt(x.Day) > parseInt(y.Day);
});
var eventsinOrder = { order: days };
Either way you go you will still need to make use of the sort function (or any equivalent) to perform the sorting while you're building this resultant object.

how to target sharedElements inside on a custom-element using neon-animated-pages

i want to use hero-animation but the target of shared elements is inside on a custom-element, and i dont know the correct syntax for this.
in the incoming page:
properties: {
animationConfig: {
value: function() {
return {
'entry': {
name: 'hero-animation',
id: 'hero',
toPage: this
}
}
}
},
sharedElements: {
value: function() {
return {
'hero': this.$.hero
}
}
}
}
In the outgoing page:
properties: {
animationConfig: {
value: function() {
return {
'exit': {
name: 'hero-animation',
id: 'hero',
toPage: this
}
}
}
},
sharedElements: {
value: function() {
return {
'hero': this.(custom element).$.hero??????
}
}
}
It's a little late, but as I had the same problem, I want to share my results:
I also was wondering how to add a button from a nested custom element to my id in sharedElements. As my intention was, that each element in polymer can "live" on it's own without any "hard-coded" dependencies to other elements, I do not wanted to reach the goal with document.querySelector etc. as this can throw errors when I remove the element containing this button.
The possibility I tried and which was working is over firing events.
The custom element containing the button fires an event on click or tab.
fireOnClick: function(e, detail) {
this.fire('wasclickedevent', {someProperties: ""});
}
Within the "Outgoing Page" - the page where the hero animation starts, I dynamically add the "sharedElements" Properties to my element, after I catched the event:
listeners: {
'wasclickedevent': '_changeSharedElement'
},
_changeSharedElement: function(e) {
this.sharedElements = {
'hero': e.target
}
},
Thats it. The hero animation works. To decouple the elements more, you can also add the entry and exit animations dynamically, as otherwise if there is no event and it exits the page, you wil get an error, that the fromPage is not found.
Hope that helps.
There is some code missing from your polymer element animationConfig property
In the incoming page
Polymer({
is: 'detail-page',
behaviors: [Polymer.NeonSharedElementAnimatableBehavior],
properties: {
animationConfig: {
value: function() {
return {
'entry': [{
name: 'hero-animation',
id: 'hero',
toPage: this
}, {
name: 'fade-in-animation',
node: this
}],
'exit': {
name: 'fade-out-animation',
node: this
}
}
}
},
sharedElements: {
value: function() {
return {
'hero': this.$.header
}
}
}
}
});
In the outgoing page
Polymer({
is: 'main-page',
behaviors: [Polymer.NeonSharedElementAnimatableBehavior],
properties: {
animationConfig: {
value: function() {
return {
'entry': {
name: 'scale-up-animation',
node: this
},
'exit': [{
name: 'hero-animation',
id: 'hero',
fromPage: this
}, {
name: 'fade-out-animation',
node: this
}]
}
}
},
sharedElements: {
value: function() {
return {
'hero': this.$.circle
}
}
}
}
});
You refer to your custom element using an ID attribute in your custom element HTML structure. The ID inside your polymer element creation in javascript ties the animationConfig and sharedElements properties of your polymer element. In the example above, the ID attribute of the custom element is header and circle, respectively.
Please post your HTML code also so we can take a better look.

angularJs filter nested object Track by

I created a custom filter, but its giving me an error
I created a fiddle here:
Fiddle
I have this user data:
data: [{
profile: {
firstName: 'John',
lastName: 'OConner'
}
}, {
profile: {
firstName: 'Smith',
lastName: 'OConner'
}
}, {
profile: {
firstName: 'James',
lastName: 'Bond'
}
}]
And I need to filter by the nested obj - profile by this
data: [{
column: {
label: 'firstName',
}
}, {
column: {
label: 'lastName',
}
}]
I can filter but is giving me this error:
this is my filter:
myApp.filter('testFilter', ['$filter',
function($filter) {
return function(items, selectedFilter) {
var returnArray = items;
var filtered = [];
var process = {};
process.filtered = [];
process.loop = function(obj, key) {
var filtered = [];
this.obj = obj;
this.key = key;
// console.log('obj--> ', obj);
// console.log('key--> ', key);
filtered = filtered.concat($filter('filter')(items, process.superFilter));
if (filtered.length > 0) {
process.filtered = filtered;
}
};
process.superFilter = function(value) {
var returnMe;
var originalValue = value.profile[process.key];
if (typeof(value) === 'String') {
originalValue = originalValue.toLowerCase();
}
if (originalValue === process.obj) {
console.log('found');
returnMe = value;
return returnMe;
}
};
if (Object.getOwnPropertyNames(selectedFilter).length !== 0) {
angular.forEach(selectedFilter, function(obj) {
filtered = filtered.concat($filter('filter')(items, obj));
});
returnArray = filtered;
// console.log('selectedFilter ', selectedFilter);
}
return returnArray;
};
}
]);
Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. How can I solve this issue?
You need to use track by as the error suggests. If you don't have a unique key to use you can use $index.
ng-repeat='talent in talents.data | testFilter:filterInput track by $index'
Here is a working example with your code: http://jsfiddle.net/hwT4P/

Resources