How to addEventListener to table row and extract data attribure - addeventlistener

I have a table with data attribute of data-id for each row
<tr class="tableRow" data-id="{{this.id}}">
<td>{{this.first_name}}</td>
<td>{{this.last_name}}</td>
<td>{{this.email}}</td>
</tr>
I'd like to add an EventListener to each row and then extract the id when a row is click.
Here is what I'm trying but is not working:
const rowClick = document.querySelectorAll(".tableRow");
rowClick.addEventListener("click", function() {
console.log("row was clicked");
const id = rowClick.getAttribute("data-id");
console.log(id);
});
Pls help.

you can use Data Tables plugin to create table. https://datatables.net/ it has inbuilt functions to click row and do something.

Related

How to conditionally change values of a Google Sheet using another Sheet

I am trying to modify an existing Google Sheet using a Form response sheet. Suppose in the sheet I need modified I have column G called "Annotated Asset ID" which contains a list of asset IDs. Now in the form response sheet there are two columns; Old ID (D) and New ID (E). I would like to check Column G of the existing sheet to see if it contains the Old ID and if it does I need to replace it with the New ID.
What is a good way to do this?
Form Response:
Existing Sheet:
Answer:
You can do this with Apps Script.
Steps:
Extract out the old and new IDs from the form response sheet
For each of the old IDs, use a TextFinder to search your column for the old ID in the existing sheet:
const cell = sheet.getRange("G1:G").createTextFinder("old-id").findNext()
Replace the ID if cell isn't null:
if (cell) { cell.setValue("new-id") }
Code Example:
function replaceIds() {
const ss = SpreadsheetApp.getActiveSpreadsheet()
const formResponseSheet = ss.getSheetByName("response-sheet-name")
const existingSheet = ss.getSheetByName("existing-sheet-name")
const oldIds = formResponseSheet.getRange("D1:D").getValues().flat()
const newIds = formResponseSheet.getRange("E1:E").getValues().flat()
const rangeToCheck = existingSheet.getRange("G1:G")
oldIds.forEach(function(id, index) {
let cell = rangeToCheck.createTextFinder(id).findNext()
if (cell) {
cell.setValue(newIds[index])
}
})
}
Add this to your project from the Tools > Script editor menu item. Make sure to change the response sheet nad existing sheet names.
Save the script and run the function. You will need to authorise it to run on your behalf.

Import Specific Google Sheet Data into WebApp

I am trying to develop a WebApp in which user enters his/her id and script will search that ID in the Google sheet and retrieve the respective data row from sheet which contains that ID. Now script is searching the ID in sheet and retrieve the specific row as an array. But I want to import that data in Table in WebApp. But couldn't find any reasonable solution. Following is the script:
function doGet() {
return HtmlService
.createTemplateFromFile('Index')
.evaluate();
}
function FetchData(val) { //'val' is entered by user in WebApp
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName("Sheet1");
var lc=formSS.getLastColumn();
var lr=formSS.getLastRow();
for (var i=2;i<=lr;i++)
{
var UID = formSS.getRange(i, 1).getValue();
if (val==UID) //Searching Google Sheet ID's and User Entered ID
{
var res=formSS.getRange(i, 1, 1,lc).getValues()[0];
return res; //contains the data of specific row which we want to put in WebApp Table
}
}
}
This is HTML Code
<body>
<script>
document.getElementById("btn").addEventListener("click",SearchID);
function SearchID() //Searching ID in Google Sheet
{
var id=document.getElementById("userid").value;
google.script.run.FetchData(id);
document.getElementById("userid").value="";
}
</script>
</body>
</html>
Is there any way that we can put this data in the table of WebApp HTML page. Any Guidance would be much appreciated. This is sheet Link:
https://docs.google.com/spreadsheets/d/119wJ3sBY3coGpEo2CHDnW1hPv_WQbgRaQKUwv7HxyFY/edit?usp=sharing
As others mentioned, you need to construct a HTML table based on the results received from the server. getValues() returns Object[][], but in your case, the function returns when it finds the first result, so you have only one row.
After receiving that, your useData() function should create a TABLE element using HTML syntax, so you need to add tags like <TABLE>, <TR>, <TH> and <TD>. These tags can be added to a variable that is used to construct the table, appending tags and their contents as you iterate over the data received:
function useData(data) {
var output = document.getElementById('OutPut');
// Start building table
var html = '<table>';
// Add table header
html += `<tr>
<th>Unique ID</th>
<th>Student name</th>
<th>Course</th>
<th>Issued on</th>
<th>certificate link</th>
</tr>`;
// Add table row, assuming there's only one row based on what is being done by Apps Script
html += '<tr>';
for (var col = 0; col < data[0].length; col++) {
html += '<td>' + data[0][col] + '</td>';
}
html += '</tr>';
// Stop building table
html += '</table>';
// Add table to existing element
output.innerHTML = html;
}

Free Text Entry in Angular Material mdAutoComplete

I want my angular material autocomplete to be a list of suggestions but not requirements. However I'm not sure how to implement as their is no clear example from the Angular Material docs.
In the example below my model is $ctrl.item.category
Clearly the example below is wrong, as my model is linked to md-selected-item, but this only works if I select an item. I want the user to be able to free enter the text if the item is not in the list. Basically how autocomplete already works in most browsers.
I see plenty of questions on how to disable this, but they are not trying to disable so much as clean up the left over text when an item is not selected. In these cases when an item is not selected then the model value is null, but text is left in the input.
I want the text left int he input to be the model value if the person does not select (or a match is not made).
md-autocomplete(
md-floating-label="Category Name"
flex="50"
md-input-name="category"
md-selected-item="$ctrl.item.category"
md-search-text="catSearch"
md-items="category in $ctrl.categories"
md-item-text="category"
md-min-length="0"
md-select-on-match=""
md-match-case-insensitive=""
required=""
)
md-item-template
span(md-highlight-text="catSearch" md-highlight-flags="^i") {{category}}
My options ($ctrl.categories) is an array of strings ['Food','Liqour'] and I wan the user to be able to use one of those or free enter Tables as their choice.
In this case you should link md-search-text to your model.
If you want to implement fuzzy search you have to write the filter method yourself. Look at this example:
template:
<md-autocomplete
md-items="item in $ctrl.itemsFilter()"
md-item-text="item.label"
md-search-text="$ctrl.query"
md-selected-item="$ctrl.selected"
>
<md-item-template>
<span md-highlight-text="$ctrl.query">{{item.label}}</span>
</md-item-template>
<md-not-found>
No item matching "{{$ctrl.query}}" were found.
</md-not-found>
<div ng-messages="$ctrl.myValidator($ctrl.query)">
<div ng-message="short">Min 2 characters</div>
<div ng-message="required">Required value</div>
</div>
</md-autocomplete>
controller:
var items = [ ... ];
ctrl.itemsFilter = function itemsFilter() {
return ctrl.query ? filterMyItems(ctrl.query) : items;
};
ctrl.myValidator = function (value) {
return {
short: value && value.length < 2,
required : value && value.length < 1,
};
};
then you just need to add filterMyItems method to filter your items
To improve the answer of #masitko, I have implemented the filter in a way, that it adds the query to the filtered list. So it becomes selectable and a valid option. So it's possible to make the autocomplete a suggestion box.
I'm using ES6 in my projects. But it should be easily adaptable to ES5 code.
myFilter() {
if (!this.query) return this.items;
const
query = this.query.toLowerCase(),
// filter items where the query is a substing
filtered = this.items.filter(item => {
if (!item) return false;
return item.toLowerCase().includes(query);
});
// add search query to filtered list, to make it selectable
// (only if no exact match).
if (filtered.length !== 1 || filtered[0].toLowerCase() !== query) {
filtered.push(this.query);
}
return filtered;
}

Filtering a dropdown based on the value in another dropdown in Rails

I have a Country model. In view I have a country dropdown. If country1 is selected, all states of that country must be listed in states dropdown box. If country2 is selected, only 'others' must be displayed in the drop down box. I have jquery to do this. but how do i access a constant defined in ruby in jquery? How do I do that?
$('#country_id').change(function() {
debugger
var country = $('#country_id').val();
if (country != 'India') {
// $('#country_state').val("others");
//$('#country_state').prop("disabled", true);
$('#country_state').empty().append('<option>Other</option>');
$('#phone').focus();
}
else{
$('#country_state').empty().append('<option>indiastates*</option>');
}
})
*indiastates is a constant in ruby. How do i display that as options for dropdown?
you can try grouped_collection_select
here is the railscast http://railscasts.com/episodes/88-dynamic-select-menus-revised
For the second dropdown list, I first created an array with the values i wanted to display in the dropdown.
var states_array = new Array("xxx","yyy");
to append this into dropdown
var states_option;
for(var i=0;i<states_array.length;i++)
states_option += "<option>" + states_array[i] + "</option>";
$school_state.empty().append( states_option );

AngularJS and jqueryUI apply new index of list elements

I'm currently finishing a feature with list reordering and I'm stuck with a probably very simple thing, but I'm really sorry that I can't figure out how to solve it .... ( possibly my brain just ignores this logic :) )
The purpose is simple :
I have a list of items with a "position" data (different from $index).
I drag and drop items to change their order.
When the drag stops, all items in the list should have a new position, that'll be updated with a $resource object.
For example, after dragging I have this:
$index elem.position
0 2
1 1
2 3
should automatically change position 2->1, 1->2 and 3->3.
The problem :
With angularUI I can have the current item index but not the others in the list. So I can't change the whole list index after stopping the drag. And it's frustrating because on view, I can catch easily $index but not in controller.
Code :
in controller.js
$scope.updateSortable = {
stop: function(e, ui) {
for (var i=0; i<$scope.list.length; i++) {
var elem = $scope.list[i];
// here's don't know how to update elem.position
//elem.position = ui.item.index; // bad one, I know :)
//elem.$update();
}
},
placeholder: "xp-hightlight",
axis: 'y'
};
in html page :
<div ng-repeat="el in list">
<div>
<span class="position" ng-bind="el.position"></span>
</div>
</div>
The json items look like that :
{ id: 47, description: "my text in the list", position: 1}
Would this work for you, or do you have to have the position variable set?
<div ng-repeat="el in list">
<div>
<span class="position">{{$index + 1}}</span>
</div>
</div>
I added this to your controller 'testCtrl'. You can update the position element within the callback of this watch:
var _list;
$scope.$watch(function() {
return JSON.stringify($scope.items)
},function(_l) {
if(typeof _l !== 'undefined') {
_list = JSON.parse(_l);
console.log(_list)
}
});
I just solved the issue, and thanks to koolunix I managed the update of position directly inside the controller with this plunkr :
http://plnkr.co/edit/kDkNLSjoHbnaumk2uaOF?p=preview
The main fact was just to manage the position with the loop in list items.
elem.position=i+1;

Resources