This is a little bit complicated to explain. I need to create an object with properties from a dynamic html code. Let me explain it with an example.
I have an object with my data like this
var myObject = {Field1: 'Value1', Field2: 'Value2'};
I have an array with my object properties like this:
var myArray = ['Field1', 'Field2'];
I use the array to generate <input> in a for loop like this:
<div v-for="property in myArray">
<input type="text" :value="myObject[property]" />
</div>
Now, I need to get the values from the generated inputs (can be an object or an array).
I know i can just simply take myObject but the thing is that the values might change (The user can alter the data because is an input which is the right approach). Also I dont want to bind the inputs to myObject because even in the input values change, myObject need to remain as it initial state.
The question is how can I create a new object and bind my inputs to that new object?
The solutions:
v-model one computed like below, it has one disadvantage, Vue won't catch the modification to re-render.
create one clone myOjbect then watch it, if change, do something you like.
similar with solution 2: using v-bind, then bind input event to assign the value to another object or something else .
PS: v-model do same thing like this.
app = new Vue({ //not vue, it is Vue
el: "#app",
data() {
return {
myObject: {Field1: 'Value1', Field2: 'Value2'},
myArray: ['Field1', 'Field2'],
copyMyObject: {}, //solution 2
copyMyObject1: {} //solution 3
}
},
computed: {//solution 1
computedObject: function(){
return Object.assign({}, this.myObject)
}
},
mounted: function(){ //solution 2
this.copyMyObject= Object.assign({}, this.myObject)
this.copyMyObject1= Object.assign({}, this.myObject)
},
watch: {//solution 2
copyMyObject: function (newValue, oldValue){
console.log('copyMyObject', newValue)
//do something else you'd like
}
},
methods: {
getObject: function () {//solution 1
console.log('computedObject', this.computedObject)
console.log('myObject', this.myObject)
}
}
})
<script src="https://unpkg.com/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<button #click="getObject()">Click me!</button>
<p>The disadvantage: {{computedObject}}</p>
<div v-for="property in myArray">
<input type="text" v-model="computedObject[property]" />
</div>
<p>Org: {{myObject}}</p>
<p>Copy: {{copyMyObject}}</p>
<div v-for="property in myArray">
<input type="text" v-model="copyMyObject[property]" />
</div>
<p>Copy: {{copyMyObject1}}</p>
<div v-for="property in myArray">
<input type="text" v-bind:value="copyMyObject1[property]" #input="copyMyObject1[property] = $event.target.value" />
</div>
</div>
You create the object from the original object:
data: {
objectValues = Object.assign({}, myObject)
}
then you can use that object in your template:
<div v-for="property in myArray">
<input type="text" v-model="objectValues[property]" />
</div>
Related
So I've got this sample:
<div class="form-item">
<label for="list-0"><?php _e('List 0', 'test'); ?></label>
<input name="list[0]" type="text" id="list-0" value="">
</div>
<div class="form-item">
<input type="checkbox" name="list[0][is-current]" id="list-0-current" value="yes">
<label for="list-0-current"></label>
</div>
What I'd like to have is something like this:
list:[
[value, is_current] // say 'John', yes
,[value, is_current] // say 'Francis', false
,[value, is_current] // say 'Bob', yes
]
In Vue you can use arrays in data:
var vueapp = new Vue({
el: '#form'
,data:{
form:{
list:[]
//[...] etc..
Then in your fields you simply use v-model="form.list" in every fields of the list. But this would only record a flat array, while I need a way to have a multi one. Is it possible? How?
Make an Object:
data: {
form: [{}]
},
If this is your array:
list = [
[value, is_current],
[value, is_current],
[value, is_current],
];
Then go over this array and add each inner array to the object:
list.forEach(function(element) {
that.form.push({value: element[0], key: element[1]});
});
See this fiddle for reference:
https://jsfiddle.net/mnd8ojLh/1/
I have a problem when implementing a nested list in Angular: the view gets updated properly but, on the other side, the code is not updated on change.
I think it will be much clearer with the code:
_this.categories = injections.map(function (category) {
return {
title: category.get('title'),
object: category,
criteria: category._criteria.map(function (oneCriteria) {
return {
object: oneCriteria,
type: oneCriteria.get("type"),
min: _this.range(oneCriteria.get("range")).min,
max: _this.range(oneCriteria.get("range")).max,
key: oneCriteria.get("key"),
value: _this.range(oneCriteria.get("range")).min,
defaultValue: _this.range(oneCriteria.get("range")).min,
selected: false
}
})
}
});
_this.category = _this.categories[0];
_this.job = {
title: '',
description: '',
salaryAmount: 0,
salaryTimeUnit: _this.salaryTimeUnits[0],
category: _this.category.object,
criteria: _this.category.criteria,
location: {latitude: 48.137004, longitude: 11.575928}
};
So and, very quick here is my HTML:
<div ng-repeat="category in controller.categories">
<input type="radio" name="group" ng-value="category.object.get('title')" id="{{category.object.get('title')}}"
ng-checked="controller.category == category" ng-click="controller.category = category">
{{category.title}}
</div>
<br>
Criteria:
<div ng-repeat="criterium in controller.category.criteria">
<div class="row vertical-align">
<div class="col-xs-9">
<span ng-click="criterium.selected = !criterium.selected"
ng-class="['list-group-item', {active:criterium.selected == true}]">{{criterium.key}}</span>
</div>
</div>
</div>
The problem is the following: the value are getting updated in the view (when you click on a radio button on the category, you see the corresponding criteria(s)). But the job is for one reason that I ignore not updated although it has the same reference as the HTML (a reference to this category.criteria).
Did I miss something?
controller.job.criteria is still just a reference to controller.categories[0]. Your code should successfully update controller.category to point at whichever category you clicked on, but that does not also update the reference in your job data structure.
What you want to do is make your ngClick event a bit more robust, i.e.:
<input type="radio" ng-click="controller.updateCategory(category)" />
and then in your js:
_this.updateCategory = function (category) {
_this.category = category;
_this.updateJob(category);
};
_this.updateJob = function (category) {
_this.job.category = category.object;
_this.job.criteria = category.criteria;
};
This will update the references in your job to match the new jazz.
I would, however, recommend leveraging ngModel and ngChange in your radios instead. Like:
<input type="radio" ng-model="controller.category" ng-value="category" ng-change="updateJob(category)" /> {{category.title}}
I have these objects right here that I will use to save data from a form, and later send it to an api as JSON :
$scope.price = {}
$scope.item = {"price":$scope.price, };
I also have these field which will be used to dynamically generate inputs on a html page:
$scope.fields = [
{
name: $scope.item.title,
title: 'Title',
type: {
view: 'input'
}
},
{
name: $scope.price.regular,
title: 'Regualar Price',
type: {
view: 'input'
}
}
];
Now in order to generate the form I use this code:
<div class="form-group" ng-repeat="field in fields">
<label>{{ field.title }}:</label>
<span ng-switch on="field.type.view">
<span ng-switch-when="input">
<input
ng-model=field.name
type="text"
/>
</span>
</span>
</div>
And with this code, it is not assigning the values in the input to the objects. Is there a way to do it? I know I can do it this way:
ng-model="item[field.name]"
But that limits me to only one level of the object. I want to be able to bind nested objects. And I just can't seem to figure it out. Thank You!
I've tried to create a very simple example of the issue I'm having with AngularJS. I've got a simple scope called testScope. I also have 2 other scopes (grouped1 and grouped2) that are derived from testScope that have been altered using a grouping function found in UnderscoreJs.
script.js
var app = angular.module('testScope', []);
app.controller('mainCtrl', function($scope) {
$scope.testScope = {
test1: {
data: [
{
field1: 'blah',
field2: 'blah blah'
},
{
field1: 'test',
field2: 'test test'
}
]
}
};
$scope.createEntry = function(newEntry) {
$scope.test1.data.push({field1: newEntry.field1, field2: newEntry.field2});
};
$scope.test1 = $scope.testScope['test1'];
$scope.grouped1 = _.groupBy($scope.test1, 'field1');
$scope.grouped2 = _.groupBy($scope.test1.data, 'field1');
});
index.html
<body ng-app="testScope" ng-controller="mainCtrl">
<form ng-submit="createEntry(newEntry)">
Field1: <input type="text" ng-model="newEntry.field1" />
Field2: <input type="text" ng-model="newEntry.field2" />
<input type="submit" />
</form>
data
<div> {{ test1 }} </div><br>
grouped1
<div>{{ grouped1 }}</div><br>
grouped2
<div>{{ grouped2 }}</div>
</body>
The problem is that when I modify my scope (using the form), test1 and grouped1 will update but grouped2 will not. Why doesn't grouped2 update and how do I get grouped2 to update when the scope changes?
Please see my example:
http://plnkr.co/edit/IN8lADekDBxDp1CNf8VG?p=preview
the reference that .groupBy($scope.test1.data, 'field1') creates changes each time $scope.test1.data changes1. Since $scope works based off of the reference, changing that allows the data to become stale or outdated.
To fix this, you can simply wrap the scope in a function. Such as this:
$scope.grouped2 = function() {return _.groupBy($scope.test1.data, 'field1');};
And then just change your reference in your html like so:
grouped2
<div>{{ grouped2() }}</div>
plunkr: here
I have a bunch of angular-bootstrap buttons made using ng-repeat:
<div class="btn-group">
<label class="btn btn-primary" ng-model="???what to insert???" btn-checkbox
ng-repeat="station in stationlist">{{station.name}}</label>
</div>
where I want to insert something in ng-model, that would give me in the end an associative array, e.g., buttons[key] = true|false. Key must be e.g. station.name, that is, derived from ng-repeat object.
Note that these angular-bootstrap buttons insert true|false to connected ng-model variables; see example: http://angular-ui.github.io/bootstrap/#/buttons. The problem is that I need to have an array element in the model, so later I want iterate on the array.
Maybe you can try this :
$scope.stationlist = [
{ name: 'a', checked: true },
{ name: 'b', checked: false },
{ name: 'c', checked: true },
...
];
And bind it like :
<label class="btn btn-primary" ng-model="station.checked" btn-checkbox
ng-repeat="station in stationlist">{{station.name}}</label>