AngularJS : Watch array of objects and animate the changed property - javascript

I have a $scope collection that is continually being updated through websockets, so data is coming in about every 2 seconds.
Let's say I have this data coming in,
var socketData = [{
name: 'bob',
age: '20',
color: 'red'
}, {
name: 'jack',
age: '10',
color: 'yellow'
}]
$scope.data = socketData;
and it's changing constantly, like this for example, which could happen a number of seconds later.
var socketData = [{
name: 'bob',
age: '21',
color: 'green'
}, {
name: 'sam',
age: '22',
color: 'red'
}]
$scope.data = socketData;
and in the DOM I have this
<div ng-repeat="d in data">
<p>{{d.name}}</p>
<p>{{d.age}}</p>
<p>{{d.color}}</p>
</div>
I would like to animate (by adding a class and just having it fade in) to each property that has changed.
By using $watch, I can get the changes, but only the objects as a whole.
$scope.$watch('data', function(newVal, oldVal) {
console.log(newVal) // whole object
console.log(oldVal) // whole object
}, true);
So the problem is that I dont want to animate the entire object, but rather the property itself. So if the name changed for each object, in the dom I'd like to see the name fields change, not an entire object, just that individual change, and I'm having a difficult time achieving that.

Related

Looping ant design tag color in React Js

I use Ant Design and data which coming from API. I assume the data like this
data = [
{
name: "John",
job: "Freelancer",
},
{
name: 'Bob',
job: 'UI Designer'
},
{
name: 'Sam',
job: 'CEO'
},
{
name: 'Alex',
job: 'Mobile Dev'
},
{
name: 'Jess',
job: 'Web Dev'
},
];
I want to return the job with Tag from Ant Design which the tag has a different color
<Tag color="green">green</Tag>
<Tag color="cyan">cyan</Tag>
I have looped the data. but I don't know how to make the data have a different color tag
data.map((el) => {
//This example doesn't have color
return <Tag>{el.job}</Tag>
})
How to achieve that ? And sorry i'm not good enough in English. I hope you understand what i mean
Or you can visit code sandbox here
In your data, add a property something like tagColor for each object.
data = [
{
name: "John",
job: "Freelancer",
tagColor: "red"
},
{
name: 'Bob',
job: 'UI Designer'
tagColor: "green"
},
{
name: 'Sam',
job: 'CEO'
tagColor: "blue"
},
];
Then in the loop, use that property to dynamically add colors. Like,
data.map((el) => {
return <Tag color={el.tagColor}>{el.job}</Tag>
});
Updated
If the colors can be random, you can place all your colors in an array. And you can pick colors one by one using index or even a randomiser. Something like,
const colors = ["red", "blue", "green"];
data.map((el, i) => {
return <Tag color={colors[(i%colors.length)]}>{el.job}</Tag>
});
It will pick colors in the array one by one based on index.

How to bind function in vue js v-model?

I asked a question which might be unclear to someone. So, I deleted that question and ask again with new approach. I have an API response something like this:
{
id: 2,
name: 'Item 1',
items: [
{
slug: 'Phase 1',
values: [
{
highValue: '12',
lowValue: '8',
color: 'red'
},
{
highValue: '15',
lowValue: '5',
color: 'green'
}
]
},
{
slug: 'Phase 2',
values: [
{
highValue: '14',
lowValue: '6',
color: 'red'
},
{
highValue: '15',
lowValue: '5',
color: 'green'
}
]
}
]
},
{
id: 3,
name: 'Item 2',
items: [
{
slug: 'CBC',
values: [
{
highValue: '10',
lowValue: '7',
color: 'green'
},
{
highValue: '12',
lowValue: '3',
color: 'red'
}
]
}
]
}
I have static block for High Value, Low Value, Red & Green in my HTML. So, for those static blocks, I need to pick appropriate value from the response. For example, for High Value & Red block, I need to pick highValue from the response when color: 'red'. So, I write four function for example:
redHigh (item) {
const res = item.filter(obj => {
return obj.color === 'red'
})
return res[0].highValue
}
Now, I tried to bind the function in v-model like this way:
<v-text-field
outlined
:v-model="redHigh(sub.values)"
placeholder="High"
></v-text-field>
But, that was not working. If I wrote :value instead of :v-model, that would work. But, in that case I don't get the changed value after clicking save button.
save (formIndex) {
console.log(this.items[formIndex])
}
How to solve that?
Codepen Demo
v-model is not for a function; it's for a Vue's data property.
However, I understand your app requirement.
You just need to create Vue computed properties, that can generate a dynamic array using a custom function bind input event from your text field
you can read $emit or v-bind documentation about it
I just read the API of v-text-field component here https://vuetifyjs.com/en/api/v-text-field/#props.
Just need to update it to use value prop and bind change event
Which is would be like this
<div v-for="(sub, index) in item.items" :key="sub.slug">
<v-text-field
outlined
:value="redHigh(sub.values)"
#change="updateSubValue(index, 'red', 'high')"
placeholder="High"
></v-text-field>
updateSubValue(index, color, value) {
// find current sub by index
// find current value's key by color and value
// update vue data
}
It might index first, been a long time I don't develop the Vue app
<div v-for="(index, sub) in item.items" :key="sub.slug">
Or you can find the current sub by slug, no need to add index

Using ng-options with JSON data

I'm still trying to find my way with AngularJS. I have a JavaScript code that uses URL to return JSON data as an array. I need help with populating the same data in select using ng-options.
data to populate on the select
This isn't how you ask for help, but nevermind. Given a JSON object like this
var JsonArray = [{
id: 1,
name: 'Jane',
address: 'Jane\'s house'
}, {
id: 2,
name: 'Jill',
address: 'Jill\'s house'
}, {
id: 3,
name: 'John',
address: 'John\'s house'
}, {
id: 4,
name: 'Jack',
address: 'Jack\'s house'
}];
When you want to use ng-select with ng-options, you need to specify 3 required fields :
your table
the name that every object will take (like a for ... each loop)
The property you want to see in your options
You also can specify a track by property to give your options a given value.
<select ng-model="mySelect" ng-options="object.name for object in JsonArray track by object.id"></select>
Now, use the last piece of code, and inspect it in a brwoser. You will understand everything.
For reference :
<select ng-model="mySelect" ng-options="[object].[chosenProperty] for [object] in [yourArray] track by [object].[property]"></select>

Dynamic Editable Grid for Angular

How can I present a grid to edit children of a parent object AND allow the user to add new child objects on the same view?
If I use a table, how do I redraw the table when a new child is added? Is there a control (hopefully that does not use jQuery) which will provide something more elegant?
My object graph looks like this:
person: {
name: 'Joe Blow',
children: [
{
name: 'Mary Blow',
gender: 'F',
age: '18',
hair: 'Brown',
eyes: 'Green'
},
{
name: 'Frank Blow',
gender: 'M',
age: '21',
hair: 'Bald',
eyes: 'Blue'
}
]
}
The view must have two forms... one to add a new child (basically just a name)... and a grid to allow the properties of each child to be edited.
Side note: I'm also worried about so many children being added that the columns shrink to an unusable size OR the grid grows too wide that it distorts the app's navigation and elements on the left.

Backbone.js: Update Collection with different data

I have a Backbone Collection of Models that have different data coming in on page load than when it's fetched.
For example, the attributes coming in on page load are:
[{ name: 'cat', color: 'yellow' },
{ name: 'dog', color: 'brown' },
{ name: 'fish', color: 'orange' }]
Then, on fetch() (or otherwise updated from the server while the page lives, the data looks like:
[{ name: 'cat', current: 5, total: 100 },
{ name: 'dog', current: 6, total: 50 },
{ name: 'fish', current:7, total: 25 }]
How can I update the Backbone Collection with the new data while retaining the old data? IDs are not assigned from the server (name is guaranteed unique).
I ended up going with this. This will update the properties for models that exist while also removing models that did not come in and adding new ones.
Backbone.Collection.prototype.update = function(col_in){
var self = this,
new_models = [];
_(col_in).each(function(mod_in) {
var new_model = self._prepareModel(mod_in),
mod = self.get(new_model.id);
if (mod) {
new_models.push(mod.set(mod_in, {silent:true}));
} else {
new_models.push(mod_in);
}
});
this.reset(new_models);
};
Note the use of _prepareModel this is important so that the Models can be identified via whatever "id" property is used in the Backbone Model object.

Categories