I'm working on an autosave feature for a vue app that sends data to api every time a change is made to the vue app data. Is it possible to ignore certain properties of an objected when using a vue watch? The object has multiple values that I want to watch to auto save and only 1 or 2 that would be ignore so it doesn't seem to make sense to set up a watch function for all the properties I want but instead just ignore the 1 that I don't.
This is the basic structure of the data:
data:{
template: {
name: "Template",
id: 1,
variables: [
{
name: "v1",
color: "#fff",
group: 1,
isSelected: true
},
{
name: "v2",
color: "#fff",
group: 3,
isSelected: false
}
]
}
}
and the basic watch function:
watch: {
template: {
handler: function(){
this.save();
},
deep: true
}
}
The isSelected field for the variables in the template are used for UI purposed only and I would like the watch to ignore that field changing because they don't get saved. I don't want to have to set up a watch function for every field in variables but instead do something in the watch like:
ignore: "template.variables.isSelected"
You can't get old value for mutation object so I think creating some helper data as below temp(save old data) will help your problem .Then check old and new data ....
var app = new Vue({
el: "#app",
data:{
a: 1,
template: {
name: "Template",
id: 1,
variables: [
{
name: "v1",
color: "#fff",
group: 1,
isSelected: true
},
{
name: "v2",
color: "#fff",
group: 3,
isSelected: false
}
]
},
temp: {}
},
mounted: function() {
// this.template.variables[0].isSelected = false;
this.temp = JSON.parse(JSON.stringify(this.template));
this.$set(this.template.variables[0],"isSelected", 222);
},
watch : {
template: {
handler: function(changeVal) {
var flag = true;
for(var i in changeVal.variables) {
if(changeVal.variables[i].isSelected != this.temp.variables[i].isSelected) {
flag = false;
}
}
this.temp = JSON.parse(JSON.stringify(this.template)); // assign changed data as old data again for next process
if(flag) console.log("saveData");// this.save();
else console.log("notsave");
},
deep: true
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>
Related
I have trading view charting library i'm working on it but now i want to add custom indicator in it but i don't know how to do.
I have found the solution
pass the custom_indicators_getter in the props to trading view default props
like this
custom_indicators_getter: function (PineJS) {
return Promise.resolve([
{
name: "Bar Colorer Demo",
metainfo: {
_metainfoVersion: 51,
id: "BarColoring#tv-basicstudies-1",
name: "BarColoring",
description: "Bar Colorer Demo",
shortDescription: "BarColoring",
isCustomIndicator: true,
isTVScript: false,
isTVScriptStub: false,
format: {
type: "price",
precision: 4,
},
defaults: {
palettes: {
palette_0: {
// palette colors
// change it to the default colors that you prefer,
// but note that the user can change them in the Style tab
// of indicator properties
colors: [{ color: "#FFFF00" }, { color: "#0000FF" }],
},
},
},
inputs: [],
plots: [
{
id: "plot_0",
// plot type should be set to 'bar_colorer'
type: "bar_colorer",
// this is the name of the palette that is defined
// in 'palettes' and 'defaults.palettes' sections
palette: "palette_0",
},
],
palettes: {
palette_0: {
colors: [{ name: "Color 0" }, { name: "Color 1" }],
// the mapping between the values that
// are returned by the script and palette colors
valToIndex: {
100: 0,
200: 1,
},
},
},
},
constructor: function () {
this.main = function (context, input) {
this._context = context;
this._input = input;
var valueForColor0 = 100;
var valueForColor1 = 200;
// perform your calculations here and return one of the constants
// that is specified as a key in 'valToIndex' mapping
var result =
(Math.random() * 100) % 2 > 1 // we randomly select one of the color values
? valueForColor0
: valueForColor1;
return [result];
};
},
},
]);
},
And after this onChartReady
tvWidget.onChartReady(() => {
//Bar Colorer Demo is the name we passed in description
widget.activeChart().createStudy("Bar Colorer Demo", false, true);
})
I'm working on two vue component.sending parent component array data to child component using props.now i want to set pre-selected value in child component dropdownlist.
Here is my code sample:
props:{
// pre-selected value based on this.
userdata:{
type:[Array,Object],
required:true,
},
roles:{
type:[Array,Object],
required:true,
},
},
data(){
return{
mutableRoles:[],
}
},
and this is my view part:
//i want set pre-selected value on this dropdownlist
<select multiple v-model="mutableRoles" class="form-control">
<option v-for="(role,index) in roles" v-bind:value="role.id" >{{role.name}}</option>
</select>
I have seen many example where show only using string. but in my case both are array.
Try this:
const CurrentRole = Vue.component("current-role", {
template: `
<div>
<label>Options</label>
<select v-model="roleId" #change="changeValue">
<option v-for="v in roles" :key="v.id" :value="v.id">{{v.title}}</option>
</select>
</div>
`,
props: {
userdata: {
type: [Array, Object],
required: true,
},
roles: {
type: [Array, Object],
required: true,
}
},
data: _ => ({
roleId: null
}),
methods: {
changeValue() {
this.userdata.role = this.roles.find(e => e.id == this.roleId)
},
},
mounted() { // for initial state
this.roleId = this.userdata.role.id
},
watch: {
userdata(v) { // for changes on parent
if (v) this.roleId = v.role.id
}
}
})
new Vue({
el: "#app",
data: {
rlist: [{
id: 1,
title: "a"
}, {
id: 2,
title: "b"
}, {
id: 3,
title: "c"
}],
user: {
role: {
id: 3,
title: "c"
}
}
},
methods: {
changeUser() {
this.user = {
role: {
id: 1,
title: "a"
}
}
}
}
})
<script src="https://unpkg.com/vue#2.5.22/dist/vue.js"></script>
<div id="app">
<p>User: {{user}}</p>
<current-role :userdata="user" :roles="rlist">
</current-role/>
<button #click="changeUser">change user</button>
</div>
The select is tailored for primitive values, therefore you'll need to add helper functions.
Higher level vue frameworks such as vue-material, vuetify, element and muse-ui tend to offer components to cope with such problems with a higher abstraction level.
EDIT:
I changed the snippet in order to make it closer to your situation.
Hi this is my code,
var vm = new Vue({
el: '#el',
data: {
input: {
sorting: "",
brand: null,
model: null,
country: "all",
cap: "",
radius: ""
}
},
watch: {
input: {
handler(newInput) {
},
deep: true
}
}
});
Here I'm watching weather input object changes. But I need to watch only some items only input object. For example I need to do something if input.country changes but not when input.brand changes. Unfortunately my code is complex and can't take items out of input object.
Just watch what you need:
watch: {
'input.country': {
handler(newCountry) {
}
}
}
Declare a computed value who target this.item.country:
computed: {
itemCountry() {
return this.item.country;
}
}
And watch this new computed value:
watch: {
itemCountry: {
immediate: true,
handler(newInput) {
// do your stuff
}
}
}
Ok, I have model with one property(provider) as object. It can change at all.
There is example, where I change provider. There can be any parametrs, image can has dpi, json can has another parametr.
So, when I select anoter provider, how to merge model property(provider) and updated provider?
this.providerWasChange = function() {
// here I should update model with provider parametrs(update full object)
$scope.provider
}
https://jsfiddle.net/77z165uj/11/
Hm,
var model = {
id: '1',
name: '',
childModels: [{
id: '1.1',
name: 'item1',
provider: {
name: 'imageProvider'
options: {
transparent: false,
dpi: 96
}
}
}, {
id: '1.2',
name: 'item2'
provider: {
name: 'jsonProvider'
options: {
uppercase: true,
}
}
}]
}
$scope.providers = [{
name: 'jsonProvider',
displayNmae: "jsonProvider",
options:{
uppercase:$scope.providerOptions,
}
}, {
name: 'imageProvider',
displayNmae: "imageProvider",
options:{
transparent:$scope.transparent,
dpi::$scope.dpi
}
}];
_changeProvider = function(data) {
if (data !== null) {
for (var i = 0; i < $scope.providers.length; i++) {
if ($scope.providers[i].name === data.name) {
$scope.providers[i].options = data.options
return $scope.providers[i];
}
};
}
}
I'm looking for a fuction or angular method, that set chosen provider blank with setted options from model back. For example, I'd like to change provider of item 2 to image provider(old values(if there is coincidence) should rewrites to model(item2), other should be deleted, and new - setted)
I am starting to look at how I would get my grid edits back to a service via the datasource.
Following the documentation, I have set a local test data source as follows..
function getDataSource() {
var gridData = [
{
col1: new CellData('1', 'data1-1'),
col2: new CellData('2', 'data1-2')
},
{
col1: new CellData('3', 'data2-1'),
col2: new CellData('4', 'data2-2')
},
];
var dataSrc = new kendo.data.DataSource({
batch: true,
transport: {
read: function (e) {
e.success(gridData);
},
update: function (e) {
// batch is enabled
var updateItems = e.data.models;
// This is not called
// on success
e.success();
},
create: function (e) {
e.success(e.data);
},
destroy: function (e) {
e.success();
}
}
});
return dataSrc;
}
I have a toolbar setup (with the "Save Changes"), and this is calling the SaveChanges configuration event, how ever, just cannot see what else I need to do to get the following to occur..
Have the data sources update called
Mark the grid "on dirty" so that the red "edited" indicators on the edited cells disappear
I am having the same problem with the Add New record (though I can't get the grids "addRow" even to fire here)
I have the running example here
Any help would be great appreciated!
You need to specify the DataSource schema for this to work:
var dataSrc = new kendo.data.DataSource({
batch: false, // true would mean transport functions get multipe models in e.data
transport: {
// ....
},
schema: {
data: function (response) {
return response;
},
model: {
id: "id",
fields: {
id: {
editable: false,
defaultValue: 0 // 0 == new / unsaved row
},
col1: {
editable: true,
// new items would have that using default add button
defaultValue: {
id: 0,
CategoryName: ""
},
fields: { id: { editable: true }, display: { editable: true }
},
col2: {
editable: true,
fields: { id: { editable: true }, display: { editable: true } }
}
}
}
}
});
Also note:
grid.saveChanges will sync the DS, so you don't need to do anything in the event
There is no addRow event.
The default "create" button will try to add an empty object; since you work with nested objects, you need to add the row yourself so you can initialize the properties; thus you need a custom button and bind your action manually
(demo)