I created an InfoWindow from Google maps and I want to put a vue component (specifically an input) inside the content property and bind it to a data. I'm also using vuetify and if possible, I want to use it's VTextfield component. If not, then a regular input would be ok as well.
Example:
data
data () {
return {
inputVal: null
}
}
methods
renderInfoWindow () {
let input = /* create an input and bind it to inputVal */
return new google.maps.InfoWindow({
content: input
})
}
According to the Template Compilation section in the docs,
<input v-model="inputVal">
is this render function:
function anonymous(
) {
with(this){
return _c('input', {
directives: [{
name: "model",
rawName: "v-model",
value: (inputVal),
expression: "inputVal"
}],
domProps: { "value": (inputVal) },
on: {
"input": function($event) {
if ($event.target.composing)
return;
inputVal=$event.target.value
}
},
})
}
}
I haven't used render functions yet, so I hope this is what you need.
Related
I try to use computed to watch navigator.onLine but not work until I refresh the web?
<template><div>{{isOnline}}</div></template>
...
<scirpt>
...
computed: {
isOnline() {
return navigator.onLine;
},
},
...
</script>
Browsers api are not reactive. So whenever their value changes, Vue doesn't know about it.
To listen to navigator.onLine changes, you have to use a native event fired by the browser (see docs):
data () {
return {
online: false,
}
},
methods: {
onOffline () { this.online = false },
onOnline () { this.online = true },
created() {
window.addEventListener('offline', this.onOffline)
window.addEventListener('online', this.onOnline)
},
destroyed() {
window.removeEventListener('offline', this.onOffline)
window.removeEventListener('online', this.onOnline)
}
}
Note: be careful with SSR, window doesn't exist on server.
Like #Kaocash said browsers api are not reactive, so a watcher won't work
Original answer :
Well, computed property will be updated when data changes on your component,
what you need is a watcher :
<template><div>{{isOnline}}</div></template>
...
<script>
...
data() {
return {
isOnline: true
}
},
watch: {
'navigator.onLine'(val) {
this.isOnline = val
},
},
...
</script>
I have a DataTable and I am loading it using Angular Js, I have Created a directive and wrapped my DataTable in this directive, A common approach of wraping JQuery Plugin in Directive so that it can live in Angular Digest Cycle.
But the ng-click that is on button and coming from render Function of column in datatable is not clickable (Not Working, Angular did not compiled it). Is there any way to make it Clickable. I know the approach in which we use {{}} with ng-repeatto populate data in datatable. I'm looking a directive way, so you can tell me what is stoping ng-click from working or how to make my directive right! Please stick with directive approach. Code is following.
App.directive('jqtable', function () {
return {
restrict: 'E, A, C',
link: function (scope, element, attrs, controller) {
var dataTable = element.dataTable(scope.options);
scope.$watch('options.data', handleModelUpdates, true);
function handleModelUpdates(newData) {
var data = newData || null;
if (data) {
dataTable.fnClearTable();
dataTable.fnAddData(data);
}
}
},
scope: {
options: "="
}
};
});
And here is my Controller:-
$scope.options = {
aoColumnDefs: [{
"bSortable": true,
"aTargets": [ 1],
"render": function ( data, type, full, meta ) {
if(meta.col==1){
return data+" <a class='btn btn-sm btn-default' ng-click='showalert()' >Click me </a>"
}
}
}],
bJQueryUI: true,
bDestroy: true,
data:$scope.data
};
$scope.showalert=()=>
{
alert("Angular Compiled the Html");
}
Angular does not know you have injected elements to the DOM. You must $compile each row. You can do that in rowCallback. Since DataTables may inject new rows when the table is filtered, sorted or upon page change, you can add a compiled flag to prevent rows from being $compiled multiple times :
$scope.options = {
rowCallback: function(row) {
if (!row.compiled) {
$compile(angular.element(row))($scope);
row.compiled = true;
}
}
...
}
see http://next.plnkr.co/edit/KxwqSVXIogtXYx4I
I'm new to vuejs I want to pass an JSON object to another component within same vue instance. following show the my code. from component add-user to component view-user. I tried vue props but it didn't work
Thank you very much.
Vue.component('view-users',{
props:['user'],
template: '<span>{{ user.name }}</span>'
});
Vue.component('add-user',{
data: function(){
return {
user:{
name:'jhon',
age:'29',
}
}
}
});
var app = new Vue({
el:'#app',
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app">
<add-user></add-user>
<view-users></view-users>
</div>
Props are mostly for passing data from parent components to child components, and a child component cannot directly modify the passed data and reflect the changes on parent components. In order to pass data around every component, a good way to do it is using Vuex.
First you create the state, possibly like
const state = {
user:{
name:'john',
age:'29',
}
}
And for the simplest case, that you are not doing anything asynchronous for now, you modify the state through mutations:
const mutations = {
CHANGE_NAME(state, payload) {
state.user.name = payload
},
CHANGE_AGE(state, payload) {
state.user.age = payload
}
}
With all these in place you can create the Vue store:
const store = new Vuex.Store({
state,
mutations
})
Then use it in your Vue instance:
const app = new Vue({
el: '...',
data: { ... },
store,
// ...
})
Finally, in your components, you can access and modify the state as follows:
Vue.component('my-component', {
data() {
return {
// ...
}
},
computed() {
user() {
// this is one way to do, you can also check out mapstate
return this.$store.state.user
}
},
methods: {
// you can also check out mapMutations
changeName(val) { this.$store.dispatch('CHANGE_NAME', val) },
changeAge(val) { this.$store.dispatch('CHANGE_AGE', val) },
}
})
Here's a simple example: http://jsfiddle.net/teepluss/zfab6tzp/6/
You can also use EventBus if you app is not too big (tutorial and documentation). And for Vuex, you can check out how to use state and mutations here.
If you use variable in many component, vuex could be better idea. But if you want to pass value to component, you can use like that
<div id="app">
<add-user :user=user></add-user>
<view-users :user=user></view-users>
</div>
import AddUser from '../add-user.vue'
import ViewUser from '../view-users.vue'
var app = new Vue({
el:'#app',
components: {
'add-user': AddUser,
'view-users': ViewUser
}
});
in view-user or add-user component you can declare like that
<template><span>{{ user.name }}</span></template>
<script>
export default {
props: {
user: {
type:'your type',
required: true/false
}
},
...
}
</script>
You can use simple external state management system.
Reference
Or you can use event handling to emit an event from one component and listen for the event in another component. Reference
Also have a look at this blog post regarding sharing data between components. Link
I have an element with a model object that I want to observe like so:
<polymer-element name="note-editor" attributes="noteTitle noteText noteSlug">
<template>
<input type="text" value="{{ model.title }}">
<textarea value="{{ model.text }}"></textarea>
<note-ajax-button url="/api/notes/" method="POST" model="{{model}}">Create</note-ajax-button>
</template>
<script>
Polymer('note-editor', {
attached: function() {
this.model = {
title: this.noteTitle,
text: this.noteText,
slug: this.noteSlug
}
},
});
</script>
</polymer-element>
I want to observe changes in the model but apparently it's not possible to use modelChanged callback in the element and neither in the note-ajax-button element. What is wrong? How can I do that?
I've tried observing the fields separately, but it's not clean at all. The state of the button element you see there should change depending on the model state, so I need to watch changes for the object, not the properties.
Thanks!
To observe paths in an object, you need to use an observe block:
Polymer('x-element', {
observe: {
'model.title': 'modelUpdated',
'model.text': 'modelUpdated',
'model.slug': 'modelUpdated'
},
ready: function() {
this.model = {
title: this.noteTitle,
text: this.noteText,
slug: this.noteSlug
};
},
modelUpdated: function(oldValue, newValue) {
var value = Path.get('model.title').getValueFrom(this);
// newValue == value == this.model.title
}
});
http://www.polymer-project.org/docs/polymer/polymer.html#observeblock
Or you can add an extra attribute to your model called for example 'refresh' (boolean) and each time you modify some of the internal values also modify it simply by setting refresh = !refresh, then you can observe just one attribute instead of many. This is a good case when your model include multiple nested attributes.
Polymer('x-element', {
observe: {
'model.refresh': 'modelUpdated'
},
ready: function() {
this.model = {
title: this.noteTitle,
text: this.noteText,
slug: this.noteSlug,
refresh: false
};
},
modelUpdated: function(oldValue, newValue) {
var value = Path.get('model.title').getValueFrom(this);
},
buttonClicked: function(e) {
this.model.title = 'Title';
this.model.text = 'Text';
this.model.slug = 'Slug';
this.model.refresh = !this.model.refresh;
}
});
what I do in this situation is use the * char to observe any property change in my array, here an example of my JSON object:
{
"config": {
"myProperty":"configuraiont1",
"options": [{"image": "" }, { "image": ""}]
}
};
I create a method _myFunctionChanged and I pass as parameter config.options.* then every property inside the array options is observed inside the function _myFunctionChanged
Polymer({
observers: ['_myFunctionChanged(config.options.*)']
});
You can use the same pattern with a object, instead to use an array like config.options. you can just observe config.
I would like to port the javascript code from my page to YUI3. After reading many posts (questions and answers) here and lots of information in the YUI3 page and in tutorials I have come to the conclusion that the best way to do it is by splitting the code in modules, because it allows me to load scripts dinamically only when needed.
I would like to organize the code in different submodules which should be loaded and managed (if needed) by a core module.
I think I have understood how to dinamically load them, but the problem I have now is that I am not always able to call the public methods both within a module and form one module to another. Sometimes it works, but sometimes I get the message xxx is not a function.
Probably the question is I don't understand how to set a global namespace (for example MyApp) and "play" within that namespace.
I would like to be able to call methods the following way: MyApp.Tabs.detectTabs()... both from the methods of the main module (MyApp.Core) and from the same submodule (MyApp.Tabs).
Here is the structure of my code:
Inline javascript:
var MyAppConfig = {
"tabpanels":{"ids":["navigation"]},
"events": [{"ids": ["main_login", "dictionary_login"],
"type": "click",
"callback": "MyApp.Core.updateContent",
"params":{
}
}]
};
YUI_config = {
filter: 'debug',
groups: {
'myapp': {
modules: {
'project-myapp-core': {
fullpath: 'http://www.myapp.com/scripts/Core.js',
requires: ['node-base']
},
'project-myapp-tabs': {
fullpath: 'http://www.myapp.com/scripts/Tabs.js',
requires: ['base', 'project-myapp-core', 'history', 'tabview', 'tabview-base']
}
}
}
}
};
YUI(YUI_config).use('node', 'base', 'project-myapp-core', function(Y) {
var MyApp = {};
MyApp.Core = new Y.MyApp.Core();
Y.on('domready', MyApp.Core.begin, Y, null, application);
});
Module: Core
File: http://www.myapp.com/scripts/Core.js
YUI.add('project-myapp-core', function(Y) {
function Core(config) {
Core.superclass.constructor.apply(this, arguments);
}
Core.NAME = 'myapp-core';
Core.ATTRS = {};
var MyApp;
MyApp = {};
Y.extend(Core, Y.Base, {
initializer: function (cfg) {
},
begin: function(e, MyAppConfig) {
MyApp.Core = instance = this;
if (MyAppConfig.tabpanels) {
YUI().use('node', 'project-myapp-tabs', function(Y) {
MyApp.Tabs = new Y.MyApp.Tabs();
});
}
if (MyAppConfig.events) {
MyApp.Core.prepareEvents(MyAppConfig.events);
// I get "MyApp.Core.prepareEvents is not a function"
}
},
prepareEvents: function(e) {
},
updateContent: function() {
}
});
Y.namespace('MyApp');
Y.MyApp.Core = Core;
}, '0.0.1', { requires: ['node-base'] });
Submodule: Tabs
File: http://www.myapp.com/scripts/Tabs.js
YUI.add('project-myapp-tabs', function(Y) {
function Tabs(config) {
Tabs.superclass.constructor.apply(this, arguments);
}
Tabs.NAME = 'myapp-tabs';
Tabs.ATTRS = {};
var tabView = [];
Y.extend(Tabs, Y.Base, {
initializer: function (cfg) {
},
begin: function (tabpanels) {
},
methodA: function () {
}
});
Y.namespace('MyApp');
Y.MyApp.Tabs = Tabs;
}, '0.0.1', { requires: ['base', 'project-myapp-core', 'history', 'tabview', 'tabview-base'] });
Where should I define the global variables, the namespace...? How should I call the functions?
Thanks in advance!
-- Oriol --
Since nothing depends on project-myapps-tabs, YUI doesn't include it. Try this in your inline JS:
YUI(YUI_config).use('node', 'base', 'project-myapp-tabs', function(Y) {