I want to get the data written in two text inputs saved into variables.
This is my rtmNav.html:
<div class="rtm-nav">
<label>From:
<input type="text" name="input" ng-model="ctrl.dataa.from">
</label>
<label>To:
<input type="text" name="input" ng-model="ctrl.dataa.to">
</label>
</div>
This is the controller that already exists. I cannot change it's structure and imo it looks different compared to a classic one. I must add the variables here:
demand.js
class DemandCtrl {
constructor(ChartDataService) {
this.ChartDataService = ChartDataService;
}
$onInit() {
getData.call(null, this);
}
/////////////// THIS IS WHERE I GUESS I SHOULD ADD THE VARIABLES
this.dataa = {
from: '',
to: ''
};
////////////
}
... other methods ...
export const Demand = {
bindings: {
data: '<'
},
templateUrl: demandPageHtml,
controller: DemandCtrl
};
Probably it is not the correct way to add it here like that because I get this message from my code editor:
[js] Unexpected token. A constructor, method, accessor, or property
was expected.
Any ideas how to solve this?
Put your variable declaration into the constructor
class DemandCtrl {
constructor(ChartDataService) {
this.ChartDataService = ChartDataService;
this.dataa = {
from: '',
to: ''
};
}
$onInit() {
getData.call(null, this);
}
}
Related
How can I set a value input that uses the v-model?
I Googled for this problem but not solved
I have an input like this:
<input type="text" name="customer_email" v-model="form.customer_email" id="email">
I need to set this input value to {{ auth()->user()->email }}
TRY THIS :)
data() {
return {
form: {
customer_email: "",
}
}
},methods:{
user(){
axios.get("api/profile").then(({data})=>{
(this.user = data)
this.form.customer_emeail = this.user.email
})
},
},created(){
this.user();
}
In your controller add this
public function profile()
{
return auth('api')->user();
}
then put this in your api.php
Route::get('profile','YourController#profile');
As you are using two way data binding v-model, you can simply set this value in the vue end.
let app = new Vue({
el:"#app",
data() {
return {
form: {
customer_email: "{{ auth()->user()->email }}",
......
......
}
}
},
......
......
});
The changes are not reflected in DOM, even when the data is changing properly. Here is a very basic example to demonstrate the issue -
<template>
<input type="text" v-model="username" />
<p>{{error}}</p>
<button #click="saveData">Save</button>
</template>
<script>
export default {
data () {
model.error = ''; // adding a new property
return model; // 'model' is a global variable
}
methods: {
saveData() {
if (!this.username) {
this.error = 'Please enter the username!';
return;
}
// ... other code
}
}
};
</script>
After calling saveData() the error variable contains the message if username is not filled. But it's not showing up in the paragraph.
There is a trick. If I also change the username property when the error variable is changed, the changes are reflected.
You need to return error or Vue doesn't have access to it.
data () {
return {
error: '',
model: model,
};
}
You should be able to achieve what you're trying to do, as long as error and username properties are defined on model for data. I've included a simple snippet below, showing it working. Take a look at Declaring Reactive Properties in the documentation.
var model = {
username: "Default"
};
new Vue({
el: "#app",
data: () => {
model.error = model.error || "";
return model;
},
methods: {
updateError() {
this.error = "Test";
},
updateUsername() {
this.username = "Hello, World!";
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button type="button" #click="updateError">Update Error</button>
<button type="button" #click="updateUsername">Update Username</button>
<div>Error: {{error}}</div>
<div>UserName: {{username}}</div>
</div>
In my Drupal 7 site's html I have this
<script>$L = $L.wait(function() {
(function($) {
Drupal.behaviors.related_products = {
attach: function (context, settings) {
artiklar = Drupal.settings.related_products.artiklar;
console.log(artiklar);
}
};
})(jQuery);
});</script>
In the variable artiklar above I have some data that I have passed from the server side using Drupal behaviors. Now, on the client side I need to access the variable artiklar in a Vue component, like so:
Vue.component('artikel-lista', {
template:`
<ul>
<artikel v-for="artikel in artiklar">{{ artikel.title }} Pris: {{artikel.price}} <a :href="artikel.link" class="button tiny" target="_blank">Läs mer</a></artikel>
</ul>
`,
data(){
return {
artiklar: "",
};
},
mounted: function(){
this.artiklar = artiklar // how can I access the variable "artiklar" here
},
});
The data in the variable consists of an array of items, that I need in my Vue component. But how can I pass the variable from within the script tags to the Vue instance, that lives in a separate file, inserted just before the ending body tag. Anyone?
If you have data in the globally visible Drupal.settings.related_products.artiklar object then you can refer to it practically the same way in Vue.js. or if you must use this function, assign data to global scope window.*.
new Vue({
template: `<div>{{foo}} / {{bar}}</div>`,
data() {
return {
foo: Drupal.settings.related_products.artiklar,
bar: window.artiklarData
};
}
}).$mount("#app");
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">Vue App</div>
<script>
// simulate global variable
var Drupal = {
settings: {
related_products: {
artiklar: ['fus', 'ro', 'dah']
}
}
};
(function() {
window.artiklarData = Drupal.settings.related_products.artiklar;
})();
</script>
If you assign the value to Drupal.settings.related_products.artiklar after creating the Vue object, you can try to use the solutions described in the documentation, e.g.
const vm = new Vue({
template: `<div>{{foobar}}</div>`,
data() {
return {
foobar: 'Initial value'
};
}
}).$mount("#app");
setTimeout(() => {
// simulate global variable
var Drupal = {
settings: {
related_products: {
artiklar: 'Changed value'
}
}
};
(function() {
vm.foobar = Drupal.settings.related_products.artiklar;
})();
}, 2000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">Vue App</div>
Maybe you could use RxJS but I don't have enough knowledge to tell if it's true and give an example.
Just in case anyone else is struggling with the same thing, I post this answer to my own question (I accidentally posted the question with the wrong account). In the end it turns out that the answer from Gander was correct and that I could access the variable directly in the Vue component, w/o first stashing it an a global variable. The viewed result was kind of weird though and after some trialling I found out that I had to parse the result with JSON.parse(). This is the working code now:
Vue.component('artikel-lista', {
template:`
<ul>
<artikel v-for="artikel in artiklar">{{ artikel.title }} Pris: {{artikel.price}} <a :href="artikel.link" class="button tiny" target="_blank">Läs mer</a></artikel>
</ul>
`,
data(){
return{
artiklar:""
}
},
mounted:function(){
this.artiklar = JSON.parse(Drupal.settings.related_products.artiklar);
console.log(this.artiklar);
}
});
I've written a directive which adds a class based on a condition - see snippet at the bottom of the question.
It works as expected in the following simple usage scenario for a required field:
<input type="text" name="lastName" ng-model="$crtl.lastName" my-directive="$crtl.isLastNameValid()" required>
However in the following scenario where I have two dependent elements using ng-required it blocks input on the element in which I don't type initially.
i.e. if I type in email it blocks input into mobile and visa versa - other than that is works fine, used as:
<input type="email" id="email" name="email" ng-model="$ctrl.emailAddress"
ng-required="$ctrl.mobileNumber.length === 0" my-directive="$ctrl.isEmailValid()">
<input type="tel" id="mobile" name="mobile" ng-model="$ctrl.mobileNumber"
pattern="(?:\+?61|0)4 ?(?:(?:[01] ?[0-9]|2 ?[0-57-9]|3 ?[1-9]|4 ?[7-9]|5 ?[018]) ?[0-9]|3 ?0 ?[0-5])(?: ?[0-9]){5}"
ng-required="$ctrl.emailAddress.length === 0" my-directive="$ctrl.isMobileValid()">
Where am I going wrong? I am compiling the element based on the condition passed in I am assuming it has something to do with that?
export const myDirective = ($compile: ng.ICompileService): ng.IDirective => {
return {
restrict: 'A',
scope: true,
compile: (element: ng.IAugmentedJQuery, attrs: ng.IAttributes): ng.IDirectivePrePost => {
var condition = attrs['myDirective'];
element.removeAttr('my-directive');
if (condition) {
element.attr('ng-class', `{ "validation-error": ${condition} }`);
return {
pre: () => { },
post: ($scope: ng.IScope, element: ng.IAugmentedJQuery) => {
$compile(element)($scope);
}
};
}
return {
pre: () => { },
post: () => { }
};
}
};
};
If you want a directive that adds and removes a class based on a condition defined by an angular expression:
app.directive("myDirective", function () {
return function postLink (scope, elem, attrs) {
scope.$watch(attrs.myDirective, function(newBool) {
if (newBool) {
attrs.$addClass("validation-error");
} else {
attrs.$removeClass("validation-error");
};
});
};
});
On every digest cycle, the directive evaluates the Angular Expression defined by the my-directive attribute and if the expression changes, it either adds or removes the validation-error class based in the truthyness of the Angular Expression.
I have a form and a live preview of what the form will create.
My model
//campaign.js
export default Model.extend({
title: attr('string'),
body: attr('string')
});
In the route
// new.js
export default Ember.Route.extend({
model () {
return this.store.createRecord('campaign', {
title: null,
body: null
})
}
});
My current implementation uses a component for the input
export default Ember.Component.extend({
keyPress(event) {
// binding code
}
});
And in the template
{{#title-input}}
{{/title-input}}
<div id="title-preview"></div>
My Feeling is that there is a cleaner or more idiomatic way to do this. I am new to ember so thank you for any help
While the use of Components are compelling they aren't required for capturing form input in ember. For what what its worth. For simple form input the route could be:
setupController() {
Ember.set('controller','newCampaign', {}); //set empty newCampaign
},
# Action hash would create the new record but only when you have some data.
actions: {
createCampaign(newCampaign) {
let newRecord = this.store.createRecord('campaign', newCampaign); //create record
newRecord.save().then(( /* response */ ) => {
this.transitionTo('campaigns'); //transition to different page.
}, (error) => { // Deal with an adapter error
//handle error
//rollback if necessary
});
}
}
The form or template could be:
{{input name="title" id="title" value=newCampaign.title type="text"}}
{{input name="body" id="body" value=newCampaign.body type="text"}}
Just a suggestion.
Jeff