Vue.js Parameterised variable names - javascript

I'm trying to parameterise variable names so they can be passed as properties into my component. In the example below I want to use this to pass the names of the item variables into the array so I can selectively display them as columns in a table without the binding having to know the item variable names.
<div id="myApp">
<h2>parameterized variable names</h2>
<table>
<tr>
<th v-for="label in labels">{{label}}</th>
</tr>
<tr v-for="item in items">
<td v-for="label in labels">{{item.label}}</td>
</tr>
</table>
</div>
My Vue instance looks like this -
new Vue({
el: '#myApp',
data: {
labels:[
'text',
'value'
],
items:[
{text: 'One', value: 'A', something:'12'},
{text: 'Two', value: 'B', something:'67'},
{text: 'Three', value: 'C', something:'66'}
]
}
});
This doesn't work because it is attempting to render a variable called 'label' in the declaration {{item.label}}. How can I tell it that 'label' is not the literal variable name?

You can use array syntax in Vue.js templates, so the following should work:
<td v-for="label in labels">{{ item[label] }}</td>

Related

problems passing parameters in winds in vue js

I have this code and I get an array in the info variable. The problem is in the delete button that calls the remove function passing the id as a parameter but it passes the first id to all elements so when I delete any element it deletes the first one instead of referring to the button
<tr>
<th scope="row">{{info.product_key}}</th>
<td>{{info.name}}</td>
<td>{{info.quantities}}</td>
<td>{{info.quatities_sold}}</td>
<td>{{info.cost_price}}</td>
<td>{{info.sale_price}}</td>
<td><button #click="showEditModal" class="btn btn-warning">editar</button></td>
<EditProductModal
:_id=info._id
:product_key=info.product_key
:product_name=info.name
:quantities=info.quantities
:quantities_sold=info.quatities_sold
:cost_price=info.cost_price
:sale_price=info.sale_price
:categories=info.categories
/>
<td><button #click="remove(info._id)" class="btn btn-danger">excluir</button></td>
</tr>
</tbody>```
As you said I get an array in the info variable but looks like instead of iterating you are directly using it. If you are iterating it properly using v-for it should pass the correct ID.
Working Demo :
const app = new Vue({
el: '#app',
data: {
info: [{
'_id': 1,
'name': 'alpha'
}, {
'_id': 2,
'name': 'beta'
}, {
'_id': 3,
'name': 'gama'
}]
},
methods: {
remove(itemID) {
console.log(itemID);
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<table>
<tr v-for="item in info" :key="item._id">
<td>{{item.name}}</td>
<td><button #click="remove(item._id)">excluir</button></td>
</tr>
</table>
</div>

Dots in bracket to access nested property

Consider the object below:
var item = {
id: 'some-id',
price: 12,
customer: {
id: 'fake-id',
name: 'fake-name'
}
};
We can access the customer name using "dots" or "brackets" as below:
item.customer.name
item['customer'].name
item.customer['name']
item.['customer']['name']
Question
In Javascript or Typescript, is there a way to access customer name like the following?
item['customer.name'] or item[customer.name]
Notes
In angular I created a reusable table component based on the mat-table, which includes pagination, sort filter and bunch of other functions... I use the following for the column definitions:
mytable.component.ts:
export interface MyTableCol {
id: string;
title: string;
// some other settings...
}
mypage.component.ts:
cols: MyTableCol[] = [
{id: 'price', title: 'Total Price'},
{id: 'customer.name', title: 'Customer Name' }
];
mypage.component.html:
<my-table [columns]="cols"></my-table>
mytable.component.html:
<ng-container [matColumnDef]="col.id" *ngFor="let col of columns">
<th mat-header-cell *matHeaderCellDef mat-sort-header>
{{ col.title}}
</th>
<td mat-cell *matCellDef="let element">
{{ element[col.id] }}
</td>
</ng-container>
However, for the nested properties (customer.name) this won't work. I think the reason is the line: element[col.id] converts to element['customer.id'] in case of the customer name column.
How can I resolve this?
It won't work automatically to pass a string like that to access the properties, you need to create a getter function like lodash _get and use it to find the value you need. And then write something like:
{{ _getAtr(element, col.id) }}

Passing parameter by variable in $location search angularjs

I'm trying to pass variable in filter object to search relevant field but when I put object without passing variable like underneath it works fine:-
stock.controller.js
var vm = this;
vm.stocks = [
{
itemName:'Peanut',
labelName: 'Fortune nuts',
cost : '$4'
},
{
itemName:'Sandwich',
labelName:'Coast Food',
cost: '$10'
}
]
vm.searchOptions = {itemName:vm.search};
stock.html
<input type="text" ng-model="vm.search"/>
<tr ng-repeat="s in vm.stocks | filter:{itemName:vm.search}">
<td>{{s.itemName}}</td>
<td>{{s.labelName}}</td>
<td>{{s.cost}}</td>
</tr>
But in case when I get object from variable It won't work. Following I pass variable vm.searchOptions instead of writing it hard coded.
<tr ng-repeat="s in vm.stocks | filter:vm.searchOptions">
<td>{{s.itemName}}</td>
<td>{{s.labelName}}</td>
<td>{{s.cost}}</td>
</tr>

Print only unique values inside ng-repeat

I have the following code snippet:
<tr ng-repeat="val in myObj">
<td>{{val.Action}}</td>
<td>{{val.Tx}}</td>
<td>{{val.Qty}}</td>
<td>{{val.Price}}</td>
</tr>
I want to print {{val.Action}} only if it is the first unique value in the list. Else I want to print empty space "". Is it possible to do this by creating a filter? Or any other way?
You can solve your problem by checking previous element(items[$index-1]) and, if it's Action field equals current one(items[$index-1].Action == val.Action) you should write empty string, otherwise value. For correctnes of this algoritm, you should implement sorting by this field. As you have filter and orderBy, you can't just write myObj[$index-1], because myObj array and filtered&sorter array(items) not the same, so you should apply assigning: items = (myObj...
angular.module('app', []).controller('MyController', ['$scope', function($scope) {
$scope.myObj = [
{Action:'Action3', Tx:4, Symbol: 'a' },
{Action:'Action1', Tx:1, Symbol: 'c' },
{Action:'Action2', Tx:3, Symbol: 'b' },
{Action:'Action3', Tx:5, Symbol: 'a' },
{Action:'Action1', Tx:2, Symbol: 'c' },
{Action:'Action3', Tx:6, Symbol: 'a' }
];
}])
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<body ng-app="app">
<div ng-controller="MyController">
<input type='text' ng-model='someValue' ng-init='someValue="a"'/>
<table>
<tbody>
<tr ng-repeat="val in items = (myObj | filter : { Symbol: someValue } | orderBy: 'Action')">
<td>{{(items[$index-1] && items[$index-1].Action == val.Action) ? '' : val.Action}}</td>
<td>{{val.Tx}}</td>
<td>{{val.Symbol}}</td>
</tr>
</tbody>
</table>
</div>
</body>

Ember tabular form with objects for rows and property names for columns

I am trying to create a modular tabular form that takes an input of 1) an array of objects (the rows) and 2) an array of property names of those objects (the columns). Through these two arrays, it should retrieve properties that can be modified through Ember.TextFields in the form.
I cannot figure out how to do this. I can retrieve the values of the properties (as shown in the code below) but they are raw values, rather than references, so the bindings to these do not update the objects' properties.
View
App.SomeTabularForm = Em.View.extend({
template: <see below>,
things: [
Em.Object.create({ foo: 'a', bar: 'b' }),
Em.Object.create({ foo: 1, bar: 2 })
],
fieldNames: ['bar', 'foo'],
thingsWithFields: function() {
var fieldNames = this.get('fieldNames');
var thingWithFieldsProxy = Em.ObjectProxy.extend({
fields: function() {
var thing = this;
return fieldNames.map(function(fn) {
// FIX: this returns a raw value which is not bindable in a template
return thing.get(fn);
});
}.property()
});
return this.get('things').map(function(t) {
return thingWithFieldsProxy.create({ content: t });
});
}.property('things.[]', 'fields.[]')
});
Template
<table>
<tr>
{{#each view.fieldNames}}
<th>{{this}}</th>
{{/each}}
<tr>
{{#each view.thingsWithFields}}
<tr>
{{#each fields}}
<td>
{{! FIX: does not actually bind to thing's property }}
{{input type="text" valueBinding="this"}}
</td>
{{/each}}
</tr>
{{#each}}
</table>
You need to specify template name,
App.SomeTabularForm = Em.View.extend({
templateName: "mytemp",
....
the template
<script type="text/x-handlebars" data-template-name="mytemp">
{{blah}}
<table>
<tr>
{{#each view.fieldNames}}
<th>{{this}}</th>
{{/each}}....
http://jsfiddle.net/EdWG3/3/
If you want to use the template property,
App.SomeTabularForm = Em.View.extend({
template: Em.Handlebars.compile("<div>{{#each field in view.fieldNames}}{{field}}<br/>{{/each}}</div>"),
things: [...
http://jsfiddle.net/EdWG3/4/
If you use it in the context of routing then you need to modify the name of the view,
http://jsfiddle.net/EdWG3/2/
EDIT
In order to bind to the proxy objects
the template needs to modified as follows,
{{#each view.thingsWithFields}}
<tr>
<td>
{{! FIX: does not actually bind to thing's property }}
{{input type="text" valueBinding="content.bar"}}{{input type="text" valueBinding="content.foo"}}
</td>
</tr>
{{/each}}
http://jsfiddle.net/EdWG3/7/

Categories

Resources