I have my vue instance:
var testOptions = new Vue({
el: '#testOptions',
methods: {
getURL: function () {
return (window.location.href);
},
testOne: function () {
console.log('!!');
},
testTwo: function () {
console.log('!!!!');
}
},
data: {
shares: [
{ text: 'testOne', icon: 'ico_test1.svg',func: testOne() },
{ text: 'testTwo', icon: 'ico_test2.svg', func: testTwo() },
]
}
});
Is it possible to call my method testOne/testTwo which I pass to shares array like this:
<li v-on:click="share.func" class="test-options__option">
{{share.text}}
</li>
Yes, it is possible.
Instead of calling the function inside each share, just pass the reference to it.
You need to use this. as those are instance functions.
shares: [
{ text: 'testOne' icon: 'ico_test1.svg', func: this.testOne },
{ text: 'testTwo' icon: 'ico_test2.svg', func: this.testTwo },
]
Also, data property should be a Function that returns object (the actual data) and it's a good practice to add that property onto the top of your Vue component.
Fiddle: http://jsfiddle.net/vnef5d4c/11/
Related
The idea is to pass different objects to an input component, have them displayed there as CSV and be able to edit/validate the text and change the style depending on the validation results. Here is the code I currently have:
<div id="vue">
<base-input :cslice="c.workspace"></base-input>
</div>
javascript:
(function () {
Vue.component('base-input', {
props: ['cslice'],
data: function () {
return {
colors: ['red', 'white', 'yellow', 'green', 'orange', 'purple'],
ind: 1
}
},
computed: {
str: {
get: function () {
return Object.values(this.cslice).join(", ");
},
set: function (val) {
if(val.indexOf('0'))
this.ind = Math.floor(this.colors.length * Math.random());
},
},
styleObj: {
get: function () {
return { color: this.colors[this.ind] };
},
set: function () {
},
}
},
template: '<div><input v-model="str" :style="styleObj" type="text"/></div>'
});
let vue = new Vue({
el: '#vue',
data: {
c: {},
},
created: function () {
this.c = Object.assign({}, this.c, {
workspace: { width: 820, height: 440 },
});
},
});
})();
Here is the fiddle:
https://jsfiddle.net/tfoller/sz946qe2/3/
This code allows me to delete the last character only if the new style is the same as the current, otherwise the text is practically uneditable, how do I fix this problem so I'm able to normally edit the input field?
Since the computed in the child uses a prop in its getter, you need to $emit back up a value with the same shape in its setter:
set: function (val) {
const arrValues = val.split(',').map(v => v.trim());
console.log(arrValues);
this.$emit('input', {
width: arrValues[0],
height: arrValues[1]
})
},
That means reversing some of the string formatting stuff you were doing in order to get the right shape.
Listen for that input event in the parent. You can change your prop name to value so that you can use v-model as the listener:
<base-input v-model="c.workspace"></base-input>
Move all of the color changing functionality into a separate method in the child that's triggered by changing the input as well. Here's a demo:
Demo
I have an Electron app with 3 windows and each window has a different menu. The menu template code for each menu is quite long and I would like to externalize it. So far nothing I have tried works.
I've tried different ways to "modularize" it but got lots of errors. The approach below works to set up the menu, but none of the functions referenced in the menu work (e.g. quitApplication).
Is what I am trying to do not possible or am I just "doing it wrong"?
var test = require("./app/js/menuTest.js");
var tm = new test();
var menuTemplate = tm.getMenu();
myWindow = Menu.buildFromTemplate(menuTemplate);
menuTest.js
function testMenu() {
this.getMenu = function () {
var menuTemplate = [
{
label: global.productData.appName,
submenu: [
{ label: 'About ' + global.productData.appName, click: () => { showAboutWindow() } },
{ type: 'separator' },
{ role: 'hide' },
{ role: 'hideothers' },
{ role: 'unhide' },
{ type: 'separator' },
{ label: 'Quit', click: () => { quitApplication() }, accelerator: 'CmdOrCtrl+q' }
]
// code deleted for clarity
return menuTemplate;
}
}
module.exports = testMenu;
From how I understand your question, you want to move the template code out of your main process script, but keep the functions in there.
This can be achieved by moving the menu structure object into a separate module. The module exports a function that takes an object with references to the functions you want to call in the menu.
I believe this does not add significant complexity and "externalizes" just the menu template code.
menu1.js:
module.exports = function(actions) {
return [
{
label: "Foo",
submenu: [
{ label: "Bar", click: actions.bar },
{ label: "About", click: actions.about }
]
}
];
}
main.js:
const {app,BrowserWindow,Menu} = require("electron");
const actions = {
bar: function () {
console.log("bar");
},
about: function () {
console.log("about");
}
};
const menu1_template = require("./menu1.js")(actions);
const menu1 = Menu.buildFromTemplate(menu1_template);
Menu.setApplicationMenu(menu1);
let mainWindow;
app.on("ready", function() {
mainWindow = new BrowserWindow();
});
I have a vue application where I watch an array for changes. This is working fine. But I'm not sure how to get the index of the array item which has changed, as the watch callback only passes in the old/new values.
Demo: http://jsfiddle.net/q3zd4fmv/
Simplified Example:
new Vue({
el: '#demo',
data: {
things: [{foo:1}, {foo:2}]
},
watch: {
things: {
handler: function (val, oldVal) {
alert('a thing changed')
},
deep: true
}
},
methods: {
change: function () {
this.things[0].foo = 5
}
}
})
Unfortunately, not out of the box. Using a combination of argument destructuring and a custom watch function, you can achieve something that should do it. For example;
new Vue({
el: '#demo',
data: {
things: [{foo:1}, {foo:2}]
},
methods: {
change: function (...args) {
let [thing, after, before] = args;
console.log(thing);
}
},
mounted: function(){
this.things.forEach(thing => {
this.$watch(() => thing, this.change.bind(null, thing))
});
}
})
My app has multiple screens and I want to store properties for each screen in an object. I want to be able to reference it easily by name, for instance:
var homelabel = screen('home').label;
or
var settingsIcon = screen['settings'].icon;
How would this be done?
let screen = {
"home": {
"icon": "home_icon.png",
"label": "home_label"
},
"settings": {
"icon": "settings_icon.png",
"label": "settings_label"
}
}
console.log(screen["home"].label);
console.log(screen["settings"].icon);
screen must be a function that returns an object with whatever passed to the function. You can move screens variable out of the function, and then you can access it directly through reference.
var screens = {
home: {
label: 'Home',
icon: 'fa fa-home'
},
settings: {
label: 'Settings',
icon: 'fa fa-cog'
}
};
function screen(screenType){
if(screenType in screens){
return screens[screenType];
}
return {};
}
var home = screen('home').label;
console.log(home);
console.log( screens['home'].icon );
To have it just in your question, create a function and return an object. If the property you call the function with doesn't exist, you should return an empty object to avoid errors.
function screen(prop) {
let obj = {
home: {
label: 'foo'
},
settings: {
icon: 'bar'
}
};
return obj[prop] || {};
}
console.log(screen('home').label); //foo
console.log(screen('foo').bar); //undefined
I have an object that defines the name and parameters of a function to be called in the click event of a page element.
object_array = [
{
id: "id1",
onclick: "load_file(filename.php);",
},
{
id: "id2",
onclick: "open_url('http://url.com');",
}
];
That information must be retrieved dynamically. I'd like in the click event to call the onclick function for a given object in the array.
$('element').click(function() {
// call object.onclick
});
Seems that eval() is not a good choice. Is there a different way of calling that function?
You should refactor the object_array to:
[{
id: "id1",
action: "load_file",
url: "filename.php"
}, {
id: "id2",
action: "open_url",
url: 'http://url.com'
}];
Then you can call it with:
var actions = {
load_file: function(url) {
...
},
open_url: function(url) {
...
},
...
};
object_array.forEach(function(ob) {
$("#"+ob.id).click(function() {
actions[ob.action](ob.url);
});
});
If you have more complex arguments, you could also deliver an arguments array instead of url and use apply() on the function.
Or, if you just want a lookup-table of functions, use:
var object = {
"id1": function() {
load_file('filename.php');
},
"id2": function() {
open_url('http://url.com');
}
};
$('element').click(function() {
object[this.id]();
});
Here's a working jsfiddle:
http://jsfiddle.net/Zh6Fv/1/
Like so:
object_array = [
{
id: "id1",
// Encapsulate in an anonymous function
onclick: function(){ load_file('filename.php'); },
},
{
id: "id2",
// Encapsulate in an anonymous function
onclick: function(){ open_url('http://url.com'); },
}
];
Then actually bind it it like this ::
$('element').click(obj.onclick);
Presumably you would be using it like this::
object_array.forEach(function(obj){
// Note there is no need to wrap the obj.onclick
// into another anonymous function anymore!
$("#" + obj.id).click(obj.onclick);
});
Here's a working jsfiddle:
http://jsfiddle.net/Zh6Fv/1/
you can declare a function like
onclick : function()
{
action(arguments);
}