I am trying to change the style of the first row in a table, the thing is that it doesn't apply correctly, i need to know if i can change directly the css with the specific tag accessing the first row of a table.
Basicly everytime i check a checkbox it should change the color of the header of my row to blue, and if it is unchecked not.
So i do this:
<div class="col-md-3">
<label class="checkbox-inline control-label col-md-10"><input v-model="hasHeader" type="checkbox">Header Row?</label>
</div>
<table class="table table-responsive">
<tbody>
<tr v-for="(row,idx1) in tableRows" :class="{headerRowDefault: checkHeader}">
<td class="table-success" v-for="(col,idx2) in tableCols"><input v-model="table.tableGrid[idx1][idx2]" type="text" class="borderTbl" value="HEY"></td>
</tr>
</tbody>
</table>
my computed checkHeader method:
checkHeader (idx2) {
alert('CHECKHEADER')
if (this.hasHeader === true && idx2 === 0) {
return true
} else {
return false
}
}
is there a way i can on my checkbox trigger the change to the first row, i know i can apply a css style to the first row, but how can i do this on the trigger? any help?
The code should look something like this.
console.clear()
new Vue({
el: "#app",
data:{
tableRows:[1,2,3,4,5],
tableCols: [1,2,3],
hasHeader: false
},
methods:{
checkHeader (rowIndex) {
if (this.hasHeader === true && rowIndex === 0) {
return true
} else {
return false
}
}
}
})
.headerRowDefault{
background-color: blue;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/vue#2.4.2"></script>
<div id="app">
<div class="col-md-3">
<label class="checkbox-inline control-label col-md-10"><input v-model="hasHeader" type="checkbox">Header Row?</label>
</div>
<table class="table table-responsive">
<tbody>
<tr v-for="(row,idx1) in tableRows" :class="{headerRowDefault: checkHeader(idx1)}">
<td class="table-success" v-for="(col,idx2) in tableCols">{{idx2}}</td>
</tr>
</tbody>
</table>
</div>
Obviously the example uses fake data. I have no idea what the actual tableRows and tableCols should be.
Related
I have two objects one contains selected records and another contains selected fields. Now I need to populate the table dynamically by checking the column header name or value.
I referred Populate table with ng-repeat and check matching header data
Completed:
I able to add the headers dynamically to the table/columns.
Working code is in Plunker
HTML
<table class="dataTable no-footer leadTable">
<thead>
<tr role="row">
<th>
<input type="checkbox" ng-model="selectedSObject[key]" class="select_tertiary_selectAll" />
</th>
<th ng-repeat="k in sFields[key]" ng-value="{{k.name}}" style="font-weight: 400; border-right: none; background-color: #0070d2; padding: 10px 18px;">
<div> {{k.label}} </div>
</th>
</tr>
</thead>
<tbody>
<tr role="row" ng-class="odd" ng-repeat="record in value.filtered">
<td>
<input type="checkbox" ng-model="record.checked" />
</td>
<td ng-repeat="(key_1, value_1) in record" style="padding: 10px 18px;">
<div> {{value_1}} </div>
</td>
</tr>
</tbody>
</table>
JS
$scope.sFields = getSFields($scope.sObjectCSVData);
$scope.iterableRecords = getiterableRecords($scope.sObjectCSVData, allRecords)
function getiterableRecords(sCSVData, allRecords) {
var sObjectRecords = {};
if (allRecords) {
Object.entries(sCSVData).forEach(function(key) {
if (sCSVData[key[0]].filtered.length != 0) {
if (sObjectRecords[key[0]]) {
sObjectRecords[key[0]].push(sCSVData[key[0]].filtered)
} else {
sObjectRecords[key[0]] = []
sObjectRecords[key[0]].push(sCSVData[key[0]].filtered)
}
}
});
}
return sObjectRecords
}
function getSFields(sCSVData) {
var fields = {};
Object.entries(sCSVData).forEach(function(key) {
if (sCSVData[key[0]].filtered.length != 0) {
for (var i = 0; i < sCSVData[key[0]].sObjectFields.length; i++) {
if (fields[key[0]]) {
fields[key[0]].push(sCSVData[key[0]].sObjectFields[i])
} else {
fields[key[0]] = []
fields[key[0]].push(sCSVData[key[0]].sObjectFields[i])
}
}
}
});
return fields
}
Need to do:
Now I have to populate the table with the respective values by checking the column name.
I'm working in AngularJS 1.6.9
By adding small changes, Now I can able to populate the table,
The code I followed is as below,
<tbody>
<tr role="row" ng-class="odd" ng-repeat="record in value[0]">
<td>
<input type="checkbox" ng-model="record.checked" />
</td>
<td ng-repeat="k in sFields[key]" style="padding: 10px 18px;">
{{record [k.name]}} </div>
</td>
</tr>
The working code is in the below mentioned plunker,
Populate the table by checking the header name
For ref.
I'm building my first project in VueJS, and I'm having trouble getting a template to show/hide using v-if. I have a data model boolean variable (groups.categories.descEditable) that I am toggling to show/hide a template. For some reason the template isn't reactively updating itself when I change that value.
<tbody v-for="group in groups">
...
<tr v-for="cat in group.categories">
...
<td class="td-indent">
<input v-if="cat.descEditable" :value="cat.description" type="text" class="form-control">
<div v-else v-on:click="editDesc(cat.id)">{{ cat.description }}</div>
<div>{{cat.descEditable}}</div>
</td>
...
</tr>
</tbody>
methods: {
editDesc (cat_id) {
let vm = this
this.groups.forEach(function(group, gr_ind){
group.categories.forEach(function(cat, ind) {
if (cat_id == cat.id)
cat.descEditable = true
else
cat.descEditable = false
})
})
}
},
So I would like the text input to show if descEditable is true (once the div containing the description is clicked), otherwise show the div with the static description value. The descEditable property seems to be updating properly, but the v-if on the input element isn't reacting to it. I must be misunderstanding something fundamental to vuejs, just can't figure out what it is.
I think you can ditch the editDesc method entirely.
console.clear()
const groups = [
{
categories:[
{
descEditable: false,
description: "click me"
}
]
}
]
new Vue({
el:"#app",
data:{
groups
}
})
<script src="https://unpkg.com/vue#2.2.6/dist/vue.js"></script>
<div id="app">
<table>
<tbody v-for="group in groups">
<tr v-for="cat in group.categories">
<td class="td-indent">
<div v-if="cat.descEditable">
<input v-model="cat.description" type="text" class="form-control">
<button #click="cat.descEditable = false">Save</button>
</div>
<div v-else #click="cat.descEditable = true">{{ cat.description }}</div>
</td>
</tr>
</tbody>
</table>
</div>
I only want to display the span tag when they click the " Price " label to sort by lowest to highest price of items
<th id="tbl-labels" ng-click="orderByMe('price')">Price<span id="small">lowest price</span></th>
here is the full controller code
<body ng-app="app" ng-controller="MainController">
<div id="outPopUp">
<svg></svg>
</div>
<p id="search-txt">Search an item</p>
<input id="rounded" text" ng-model="searchfor" />
<div id="container">
<table border="0" width="100%">
<tr>
<th id="tbl-labels" ng-click="orderByMe('product')">Product</th>
<th id="tbl-labels" ng-click="orderByMe('price')">Price<span id="small">lowest price</span></th>
<th id="tbl-labels">Link</th>
</tr>
<tr id="tr-items" ng-repeat="deal in deals | filter:searchfor | orderBy:myOrderBy">
<td id="product">{{deal.product}}</td>
<td id="price">${{deal.price}}</td>
<td id="url">{{deal.link}}</td>
</tr>
</div>
</body>
Your span id="small" must have a ng-show or ng-hide and the expression should be updated when orderByMe is executed.
<th id="tbl-labels" ng-click="orderByMe('price')">Price<span ng-show="isLowestToHigher" id="small">lowest price</span></th>
in your scope I think you have something like
function orderByMe(property) {
...
...
if(property === 'price') {
scope.isLowestToHigher = !scope.isLowestToHigher
}
}
First of all id rename the id "small" to something more representing of what you're trying to accomplish. something like "filter-by-price".
Then in your orderByMe function:
function orderByMe(property) {
...
...
if(property === 'price') {
$("filter-by-price").addClass("lowtohigh");
}
}
Then in your css you would do something like:
#filter-by-price .lowtohigh::after {
content: " ^";
}
You could also change your function to toggle filtering and you'd just add another class to handle that.
#filter-by-price .hightolow::after {
content: " ˅";
}
Declare a variable $scope.clickedValue=false;
Make it true when the price is clicked and then use ng-show directive.
<th id="tbl-labels" ng-click="orderByMe('price')">Price<span ng-show="clickedPrice" id="small">lowest price</span></th>
Hope it helps.
I have a table where I want the last row to to display a button, but only on the last row. The code below works on showing and hiding the button, but it appears on every row.
How would I go about only displaying it on the last row?
Viewmodel:
var loadCustomFileName = function () {
for (i = 0; i < self.GetCanSeam().length; i++) {
var obj = {
appendFileName: parseFileName(i),
displayFileName: parseDisplayName(i)
if (i == self.GetCanSeam().length - 1) {
self.isMax(true);
}
};
self.GetCustomFile.push(obj);
}
};
View:
<div class="csFormField" data-bind="visible: GetCustomFile().length > 0">
<table style="width: 100%;">
<thead>
<tr>
<th>File Name Template</th>
<th>File Name Append</th>
</tr>
</thead>
<tbody data-bind='foreach: GetCustomFile()'>
<tr>
<td><p class="cs-label"><label data-bind="text: displayFileName" /></p></td>
<td><p><input class="cs-input" data-bind="textInput: appendFileName" />
<button class="addFormat" data-bind="visible: isMax">+</button></p></td>
</tr>
</tbody>
</table>
</div>
I think your isMax is initialized on parent context. Maybe try this
var obj = {
appendFileName: parseFileName(i),
displayFileName: parseDisplayName(i)
};
obj.isMax = ko.observable(i==(self.GetCanSeam().length - 1));
self.GetCustomFile.push(obj);
You can compare the index of your forloop. If it gets to the last element then visible the button.
Example :https://jsfiddle.net/kyr6w2x3/12/
self.ArrayLength = ko.observable()
self.ArrayLength(self.GetCustomFile().length);
HTML :
<button class="addFormat" data-bind="visible: $index() == $parent.ArrayLength() -1">+</button></p></td>
I have created a table/grid using jsViews. Each row has an edit button which when clicked selects the row and shows input controls instead of text values.
If I show/hide the inputs using data-link="visible{:#parent.parent.data.selectedIndex!==#index}" then it works fine.
However, I was trying a different approach using {^{if #parent.parent.data.selectedIndex===#index}}...{{else}}...{{/if}} to show/hide the inputs and this doesn't work when selectedIndex changes on my data object.
I also tried with {^{if ~root.selectedIndex===#index}} but that didn't work either. Is it possible to do this with {{if}}? The reason I am trying this over the first method that worked was to avoid rendering lots of select boxes which will just be hidden anyway.
My data object looks like this:
app = {
data: [...],
selectedIndex: null,
select: function select(index) {
if (this.selectedIndex !== index) {
$.observable(this).setProperty("selectedIndex", index);
}
}
};
I link the template like this:
$.templates("#myTemplate").link("#divHolder", app)
.on("click", ".data .editButton", function() {
app.select($.view(this).index);
})
.on("click", ".data .saveButton", function() {
// save details
})
.on("click", ".transmittals .cancelButton", function() {
// reset values
app.select(null);
});
My template is like this:
<script id="myTemplate" type="text/x-jsrender">
<table id="tblData" class="data">
<thead>
<tr>
<th></th>
<th>A</th>
<th>B</th>
<th>C</th>
</tr>
</thead>
<tbody>
{^{for data}}
<tr class="item">
<td>
{{if #parent.parent.data.selectedIndex===#index}}
<span class="editItem">
<button class="cancelButton">Cancel</button></span>
{{else}}
<span class="viewItem">
<button class="editButton">Edit</button></span>
{{/if}}
</td>
<td>
{^{if #parent.parent.data.selectedIndex===#index}}
<span class="editItem"><input type="text" data-link="B" /></span>
{{else}}
<span class="viewItem" data-link="B"></span>
{{/if}}
</td>
<td>
{^{if #parent.parent.data.selectedIndex===#index}}
<span class="editItem"><input type="text" data-link="C" /></span>
{{else}}
<span class="viewItem" data-link="C"></span>
{{/if}}
</td>
</tr>
{{/for}}
</tbody>
</table>
</script>
When you add an {{if}} block, it is a nested view, so the button click is not getting you the item view with the index. You need to use $.view(this).parent.index - or, simpler, $.view(this).getIndex() - which automatically steps up through nested views (if any) to the item view and gets its index.
app.select($.view(this).getIndex());
(See discussion here: https://github.com/BorisMoore/jsrender/issues/173#issuecomment-11058106)
BTW here is a modified form of your sample, just to give you some ideas. It uses <button data-link="{on ~root.select #getIndex()}">Edit</button> to hook up the click handler on the button and call the select method directly, passing it the index:
<script id="myTemplate" type="text/x-jsrender">
<table id="tblData" class="data">
<thead>
...
</thead>
<tbody>
{^{for data}}
<tr class="item">
{^{if ~root.selectedIndex===#index}}
<td><button class="cancelButton" data-link="{on ~root.select null}">Cancel</button></td>
<td><input data-link="A" /></td>
<td><input data-link="B" /></td>
{{else}}
<td><button class="editButton" data-link="{on ~root.select #getIndex()}">Edit</button></td>
<td data-link="A"></td>
<td data-link="B"></td>
{{/if}}
</tr>
{{/for}}
</tbody>
</table>
</script>
<div id="divHolder"></div>
<script>
var app = {
data: [{A:"aa", B: "bb"},{A:"aa2", B: "bb2"}],
selectedIndex: null,
select: function(index) {
if (this.selectedIndex !== index) {
$.observable(this).setProperty("selectedIndex", index);
}
}
};
$.templates("#myTemplate").link("#divHolder", app);
</script>