I am creating a blog article creation field, in which each field is gathered into fields: {} object.
data: {
fields: {
title: '',
slug: ''
}
},
I want to take the title and use a slugify method on that value, from which the computed should return the end-slug into the slug input.
This would work on a non-nested field:
computed: {
slug: function () {
return this.slugify(this.fields.title)
}
},
How can I access the nested field from computed?
Inputs:
<input type="text" class="form-control"
v-model="fields.title" placeholder="Enter your title">
<input v-model="fields.slug" type="text" class="form-control" disabled>
I need to use v-model on both inputs.
This works well and i get the slug, the problem is is that the data in fields.slug is not changing. How do I get my computed slug value into my fields.slug?
Related
I am not sure how to go about saving an array of strings from an input field to mongoDB with mongoose.
Ideally I would like to enter text several times in the same input field that creates an array. So I would end up having something like this.
title: "This is my Title"
actions: [ "walking", "smiling", "laughing"]
EJS File:
<form action="/blogs" method="POST">
<input type="text" placeholder="title" name="title" id="title" >
<input type="text" name="actions" id="actions" >
<button >submit</button>
</form>
blog.js
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const blogSchema = new Schema(
{
title: {
type: String,
required: true,
},
actions: [
{
type: String,
},
],
},
{ timestamps: true }
);
const Blog = mongoose.model("Blog", blogSchema);
module.exports = Blog;
app.js
app.post('/blogs', (req, res) => {
const blog = new Blog ({
title: req.body.title,
actions: req.body.tags,
});
blog.save()
.then((result) => {
res.redirect('/blogs')
})
.catch((erro) => {
console.log(erro)
})
})
Any guide on how to approach this? Right now my only solution is to create multiple input fields, but that is not correct.
If the actions tags are predefined and specific you can use html select multiple. That way actions property will be sent as an array of strings
<form action="/blogs" method="POST">
<input type="text" placeholder="title" name="title" id="title" >
<label for="actions">Actions:</label>
<select name="actions" id="actions" multiple>
<option value="walking">walking</option>
<option value="smiling">smiling</option>
<option value="laughing">laughing</option>
</select>
<button >submit</button>
</form>
And inside the controller you handle this way
// req.body.actions is already an array.
const blog = new Blog(req.body);
blog.save()
.then((result) => {
res.redirect('/blogs')
})
.catch((erro) => {
console.log(erro)
})
If, in any case, you want to use a text input to write the actions separated by space or comma, the actions property will be sent as a string. Then you can convert the string to array inside the controller.
// In case of multiple spaces, replace with single space.
// Then split string to array of strings
let actions = req.body.actions.replace(/ +/g, " ").split(" ")
const blog = new Blog ({
title: req.body.title,
actions
});
// rest of code
Whatever you choose to do, the actions will be stored as array of strings in the database.
Possibly you are sending an array as a string to the mongo. You can check this by checking the type of req.body.tags like so:
console.log(typeof req.body.tags)
If this returns a String, make sure you send the content as JSON to the database.
I'm building an application in Vuejs where I'm creating a render function for input fields. I'm emitting an input event to bind with v-model. I can see values are getting assigned while I assign/insert any values, but when I assign the other way i.e. assigning any value to v-model for input fields it shows empty or it shows the placeholder values if it is available
Here is my code:
createElement('input', {
class: 'form-control m-input',
attrs: { type: this.type, placeholder: this.placeholder },
on: {
input: (event) => {
this.$emit('input', event.target.value)
}
}
})
In props I have:
props: {
label: String,
type: String,
placeholder: String,
},
and while declaring components I do:
<nits-input
label="Email"
type="email"
placeholder="Enter your email"
v-model="email"
>
</nits-input>
In data I'm trying to assign the values:
data() {
return {
email: 'test#example.com',
}
},
How can I achieve assigning values to v-model and displaying it inside the respective fields. Help me out with this. Thanks.
v-model is really just shorthand for having a value prop and emitting an input event.
So in addition to your existing props, you need to add a value one:
props: {
label: String,
type: String,
placeholder: String,
value: String
},
I'm coordinating input elements with the keys of an object on Vuex state. Let's say I've got this object:
myObj: { foo: 1, bar: 2 }
And a computed property in a component:
myObjVals: {
get(){ return this.$store.state.myObj },
set(//?) { //? },
},
In the template, I can get values from the store:
<input type="number" v-model="myObjVals['foo']"/> // displays "1"
<input type="number" v-model="myObjVals['bar']"/> // displays "2"
But when I adjust the value on an input, I get the error: "Do not mutate vuex store state outside mutation handlers."
One obvious solution here is to have a different computed property for each key in myObj... but for larger objects, this gets repetitious/cumbersome. I am wondering if there is any way to code this as I am attempting to above, that is, using only one computed property to reference the object for both get and set functions in v-model.
Come to think of your problem once more. One solution could be something suggested here: https://vuex.vuejs.org/guide/forms.html
<input type="number" :value="myObjVals['foo']" #input="changeMyObj('foo', $event)"/> // displays "1"
<input type="number" :value="myObjVals['bar']" #input="changeMyObj('bar', $event)"/> // displays "2"
with computed property and a method:
computed: {
myObjVals: function () {
return this.$store.state.myObj
}
},
methods: {
changeMyObj(key, evt) {
this.$store.commit('changeMyObj', {key: key, value: evt.data})
}
}
With a mutation inside the store:
mutations: {
changeMyObj(state, objInput) {
state.myObj[objInput.key] = objInput.value
}
}
Here is a "working" fiddle: http://jsfiddle.net/zfab6tzp/346/
Not sure if this is the best solution possible, but it seems to be working
I am using VueJS and I have a form with two fields. The user is required to enter the first field, and I want the value of second field to be calculated using the value from first field and passing it through a method.
HTML
<div id="app">
<input type="text" v-model="value.label">
<input type="text" v-model="value.slug">
<!-- Slug value to display here -->
<br /><br />
{{value}}
</div>
Javascript
new Vue({
el:'#app',
data:{
value:{
label: '',
slug: '' // This value is calculated by passing label to santiize()
}
},
computed: {
},
methods: {
sanitize (label) {
return label+'something'
}
}
});
The user enters the first field which updates value.label
We need to pass value.label through sanitize() method and update value.slug . This should also immediately show up in the form field.I don't know how to do it. So, if the user types nothing in the form field it will have an automatic value returned as described.
Along with that it would have been awesome, if we allow the user to bypass what the santize function returns, if the user decides to type the slug value himself in the form field. So, if the user decides to type, the typed value will be set.
I created this fiddle for it - https://jsfiddle.net/9z61hvx0/8/
I was able to solve the problem by changing the data structure a bit and adding a watcher to 'label...
new Vue({
el:'#app',
data:{
label:'',
slug: ''
},
computed: {
computedSlug () {
return this.value.label+'Manish'
}
},
watch: {
label: function () {
this.slug = this.sanitize(this.label)
}
},
methods: {
sanitize (label) {
return label+'something'
}
}
});
Any other more sophesticated answers are most welcome :)
I am converting a project from Angular to Web Components / Custom Elements and am trying to replace ng-model by creating a binding for the following text field:
<input type="search" class="form-control search_input" placeholder="Search for someone new" value$="[[userLookup:input]]" required autocomplete="off">
Obviously since this is converted from Angular, I need to be able to access this value in a JavaScript function:
(function(customElements) {
class RecentSearch extends PolymerMixins.LightDomMixin(Polymer.Element) {
static get is() { return 'recent-search'; }
static get properties() {
return {
properties: {
user: {
type: Object
},
userLookup: {
type: String,
reflectToAttribute: true,
value: '',
},
},
};
}
lookupUser() {
if (this.userlookup) {
$state.go('users', { query: userlookup });
}
};
}
customElements.define(RecentSearch.is, RecentSearch);
})(window.customElements);
How would I access the userLookup property (the one bound to the text field) from inside the lookupUser function?
You're already accessing userLookup correctly from lookupUser() with this.userLookup. The event handler's context (i.e., this) is the Polymer element instance.
However, your data binding is incorrectly a one-way data binding, so userLookup would not be updated. This kind of binding needs to be two-way (i.e., with curly brackets) and cannot use attribute binding (i.e., $=).
The correct usage should be something like this:
<input placeholder="Search for someone new"
value="{{userLookup::change}}" />
demo