This is my object
var users ={
twitter : {
name : //,
lastname : //
},
facebook : {
name : //,
lastname : //
}
}
}
I have a dynamic variable activeuser that updates from Facebook to twitter.
What i'm trying to do is refer to the inner object in users depending on the value of activeuser. I need to give my div something like this class :
<div class=' {{users.activeuser}}'></div>
I know this is not how it should be done with vue.js. Do you have any suggestions?
Thank You!
Using VueJS you should be able to assign your dynamic variable to a Vue Model when you load the new object using a Vue setter $set('property name', 'value')
Example AJAX retreival:
$.getJSON('myURL.html?query=xxx', function(data, textStatus, jqXHR){
try{
MyVue.$set('dynamicObject', data);
}
catch(e){}
});
A generic Vue may look like this:
var MyVue = new Vue({
el:'#exampleDiv',
data: {
dynamicObject : ''
}
});
Bound to an example HTML element:
<div id="exampleDiv">
<label class="{{dynamicObject.activeuser}}">{{dynamicObject.username}}</label>
</div>
In the case that you have an object with an array of objects which also contain properties Vue makes it very simple to create many HTML elements (for each child object) by simply adding a v-repeat (example) to the desired HTML and assigning the datasource:
<div id="exampleDiv">
<label v-repeat="dynamicObject" class="{{dynamicObject.activeuser}}"></label>
</div>
Related
I'm using vue 2. I have a text get from api.
"Hello everyone! My name is [input]. I'm [input] year old".
Now, I have to replace the [input] with an html input and handle the onKeyUp for this input.
What I have to do?
I used computed render html, but it not work with v-on:xxx.
content.replaceAll('[answer]', '<input type="text" class="input_answer" v-on:click="handleInput()"/>')
Thanks!
After spending an hour and so on this requirement, I came up with the solution.
Here you go (I added all the descriptive comments/steps in the below code snippet itself) :
// Template coming from API
var textFromAPI = "<p>Hello everyone! My name is [input]. I'm [input] year old</p>";
// getting the array of input tags. So that we can loop and create the proper input element.
const matched = textFromAPI.match(/(input)/g);
// Iterating over an array of matched substrings and creating a HTML element along with the required attributes and events.
matched.forEach((el, index) => {
textFromAPI = textFromAPI.replace('[input]', `<input type="text" id="${index + 1}" v-model="inputValue[${index}]" v-on:keyup="getValue"/>`);
})
// Here, we are compiling the whole string so that it will behave in a Vue way.
var res = Vue.compile(textFromAPI)
var app = new Vue({
el: '#app',
data: {
compiled: null,
inputValue: []
},
render: res.render,
staticRenderFns: res.staticRenderFns,
mounted() {
setTimeout(() => {
this.compiled = res;
})
},
methods: {
getValue() {
// Here you will get the updated values of the inputs.
console.log(this.inputValue);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
</div>
Thanks # Rohit Jíndal, but!
When I use vue2 and it doesn't work. And there is an error:
TypeError: Cannot read properties of undefined (reading 'string')
I build this to a component and use anywhere in my project.
<render-html :text="question.quest_content" #handleAnswer="handleAnswer"></render-html>
I used and it's work.
this.$options.staticRenderFns = string.staticRenderFns;
return string.render.bind(this)(h)
Thanks so much!
I'm getting familiar with Vue.js after having previously used AngularJS and I'd like to find if there's any way to get around explicitly declaring every data property in data { }.
In AngularJS, it was enough to declare ng-model as an HTML attribute and when the app initializes it adds them to the scope so they can be read/manipulated.
My concern is that I have a technical calculator I'm making with about 100 individual properties and declaring each property twice seems redundant.
Does Vue offer anyway to implicitly pick up the model properties without explicitly declaring them in the app data?
Example AngularJS without explicitly declaring model properties in the app:
<script src="https://code.angularjs.org/1.6.9/angular.js"></script>
<div ng-app="exampleApp" ng-controller="exampleController">
<input ng-model="firstName" ng-change="makeName()">
<input ng-model="lastName" ng-change="makeName()">
<input ng-model="fullName">
</div>
<script>
angular.module("exampleApp", []).controller("exampleController", function ($scope) {
$scope.makeName = function () {
$scope.fullName = $scope.firstName + " " + $scope.lastName;
}
});
</script>
More or less the same app in Vue.js:
<script src="https://cdn.jsdelivr.net/npm/vue#2/dist/vue.js"></script>
<div id="exampleApp">
<input v-model="firstName" v-on:input="makeName">
<input v-model="lastName" v-on:input="makeName">
<input v-model="fullName">
</div>
<script>
var app = new Vue({
el: '#exampleApp',
data: {
firstName: "",
lastName: "",
fullName: ""
},
methods: {
makeName: function () {
this.fullName = this.firstName + " " + this.lastName;
}
}
});
</script>
Yes, for any 'variable' used in the HTML template, it must be declared in the JS.
While this can seem annoying when you have a lot of variables, it is important since the variable can be any one of a number of reactive things - simple variables, computed properties, methods etc. It wouldn't be possible to know what to create without also some syntax to specify what type of variable should be created, or to specify any default values.
In your example, fullName should probably be specified as a computed property - e.g.:
computed: {
fullName: function () {
return this.firstName + " " + this.lastName;
}
}
This way there is no need for the v-on:input - when the firstName and lastName variables update, this will trigger fullName to be recalculated.
In vuejs the elements are assigned an attribute starting 'data-v-***'
I could not find any docs about fetching this value so ended up using refs and grabbing the attributes of the main node:
<template>
<div class="m-colour-picker" ref="thisContainer">
...
</div>
</template>
const attributes = this.$refs.thisContainer.getAttributeNames();
let dataAttribute = '';
attributes.forEach((attribute: string) => {
if (attribute.substring(0, 5) === 'data-') {
dataAttribute = attribute;
}
});
But it feels a little forced.. is there a method in vue to fetch this already built in?
That has little to do with Vue.js. Data attributes for any element are automatically synced with it's internal dataset object.
Example:
console.log(foobar.dataset);
console.log(foobar.dataset.vFoo);
console.log(foobar.dataset.vBar);
// notice how data attributes containing more than the initial data- dash
// are automatically transformed to camel case:
// data-v-foo-bar ===> dataset.vFooBar
console.log(foobar.dataset.vFooBar);
// if all you care about is the names of the attributes:
console.log(Object.keys(foobar.dataset));
<div id="foobar" data-v-foo="bar" data-v-bar="baz" data-v-foo-bar="foobaz"></div>
i'm working on a vue file and have a form :
<div class="input-group">
<span class="input-group-addon">Montant</span>
<input type="number" class="form-control" v-model="amount" v-bind:value="pattern['value']"]>
</div>
my tab pattern is loaded like that :
var request = $.ajax({
url: '{{ path ('home') }}promos/pattern/'+value,
})
request.success(function(data){
if(data['pattern']==='yes'){
this.pattern=data[0];
alert(this.pattern['value']);
}
})
and my instance :
var instance = new Vue({
el: "#General",
data: {
[...]
pattern: []
}
and the request is made evertyime i do 'action a'. I have the right alert with the value i want everytime i do 'action a' but the input stays at 0 and won't dynamically change.
Something is wrong with your code. Firstly, let's look at your ajax request:
request.success(function(data){
if(data['pattern']==='yes'){
this.pattern=data[0];
alert(this.pattern['value']);
}
})
What is the form of your data response? Because you are checking something with data['pattern'], and then you are trying to associate to this.pattern something that you call data[0]
Then, as stated in #thanksd answer, you are referencing a wrong this in your ajax callback, you need to create a self variable:
var self = this
var request = $.ajax({
url: '{{ path ('home') }}promos/pattern/'+value,
})
request.success(function(data){
if(data['pattern']==='yes'){
self.pattern=data[0];
alert(this.pattern['value']);
}
})
Finally, you write:
<input type="number" class="form-control" v-model="amount" v-bind:value="pattern['value']"]>
So there are a few mistakes here. Firstly, you have a ] at the end of the line that has nothing to do here.
Secondly, you are using v-bind:value, this is not something that is going to be responsive. If you want this input to be responsive, you should use v-model and set the value of amount when you want to change the input value.
Hope this helps
Three things:
The this in your success handler is not referencing the Vue instance. You need to set a reference outside the scope of the handler and use that instead.
You can't chain a success callback to jQuery's ajax method in the first place. It's defined as a property in the parameter object passed to the call. (Maybe you copied code over wrong?)
You need to get rid of v-model="amount" if you want the input's value to reflect the value bound by v-bind:value="pattern"
Your code should look like this:
let self = this; // set a reference to the Vue instance outside the callback scope
var request = $.ajax({
url: '{{ path ('home') }}promos/pattern/'+value,
success: function(data) { // success handler should go in the parameter object
if (data['pattern']==='yes') {
self.pattern=data[0];
alert(this.pattern['value']);
}
}
})
I use the control MicrosoftNSJS.Advertising.AdControl in the ItemTemplate of a ListView.
I would like to bind some datas to the following data-win-options properties : ApplicationId and AdUnitId
The source datas are correctly set and are visible in my item template, I can display them with an h2 + a classic data-win-bind on innerText property
Ads are displayed correctly if I put directly static IDs in html code but these IDs need to be loaded from a config file...
Is it possible ? Thanks
If it's not possible, can I modify directly the item template in the JS code before to be injected in the listview ?
Come to find out this is possible (I was trying to do something similar)
The syntax for the control properties must be prefixed with winControl.
Example (I'm setting the application id here but binding the html element's className and the ad control's adUnitId)
<div id="adItemTemplate" data-win-control="WinJS.Binding.Template">
<div data-win-bind="className:css; winControl.adUnitId: adUnitId"
data-win-control="MicrosoftNSJS.Advertising.AdControl"
data-win-options="{ applicationId: 'd25517cb-12d4-4699-8bdc-52040c712cab'}">
</div>
</div>
I finally found a way to perform this without real binding, by using the itemTemplateSelector function like this :
function itemTemplateSelector(itemPromise)
{
return itemPromise.then(function (item)
{
if (item.type == "ad")
{
var template = _$(".adTemplate").winControl.render(item, null);
// Access to the AdControl through the DOM
var adControl = template._value.childNodes[1].childNodes[1].winControl;
// Set options that are specified in the item
WinJS.UI.setOptions(adControl, { applicationId: item.AdAppId, adUnitId: item.AdUnitId });
return template;
}
else
{
return _$(".itemTemplate").winControl.render(item, null);
}
}
}
I had this problem in ratings:
<div data-win-control="WinJS.UI.Rating" data-win-options="{averageRating: 3.4, onchange: basics.changeRating}"></div>
I bind it via winControl:
<div data-win-control="WinJS.UI.Rating" data-win-bind="winControl.averageRating: myrating" data-win-options="{onchange: basics.changeRating}"></div>
It worked fine.
<div data-win-bind="this['data-list_item_index']:id WinJS.Binding.setAttribute" >