I'm kinda new to Javascript so please don't bite. I wrote simple function that displays my Firebase users in table, I'm using Jquery to create this, so far my code looks like that:
userRef.on("child_added", snap => {
var username = snap.child("name").child("name").val();
var surname = snap.child("name").child("surname").val();
$("#user_table").append("<tr><td>"+ username +"</td></tr>")
});
now i want to display each users data by clicking on his nickname in table, im doing it like that :
$("#user_table").on('click', 'td', function() {
userRef.on("child_added", snap =>{
cosValue = snap.child("cos").child("cos").val();
alert(cosValue);
})
});
and it displays all of my users data.. not this specific one that i clicked on, how can i solve that ? :)
userRef.on("child_added", snap => {
var username = snap.child("name").child("name").val();
var surname = snap.child("name").child("surname").val();
var cosValue = snap.child("cos").child("cos").val();
$("#user_table").append("<tr onClick=\"displayCos(" + cosValue + ")\"><td>"+ username +"</td></tr>")
});
function displayCos(cos) {
alert(cos); //or any other action, e.g. open a PopUp window, display it in another div or table, etc.
}
You don't need the second .on("child_added",...
Also, you may do that with an onClick listener, instead of coding that inline in the tr tag (see https://www.w3schools.com/js/js_htmldom_eventlistener.asp).
Related
I have a Master-Detail ag-grid. One column has checkboxes, (checkboxSelection: true). The details grid have a custom status panel with a button. When the user clicks the button in any specific Detail grid, I don't know how to get the SelectedRows from just that one specific detail grid.
The problem is they might leave multiple details displayed/open, and then looping over each Detail Grid will include results from all open grids. I'm trying to isolate to just the grid where the user clicked the button.
I tried looping through all displayed/open detail grids to get the Detail grid ID. But I don't see any info in this that shows me which one they clicked the button in.
I tried in the button component to see if, in the params, there is anything referencing the detailgrid ID that the button is in, but I did not see anything there either.
This is the button component:
function ClickableStatusBarComponent() {}
ClickableStatusBarComponent.prototype.init = function(params)
{
this.params = params;
this.eGui = document.createElement('div');
this.eGui.className = 'ag-name-value';
this.eButton = document.createElement('button');
this.buttonListener = this.onButtonClicked.bind(this);
this.eButton.addEventListener("click", this.buttonListener);
this.eButton.innerHTML = 'Cancel Selected Records <em class="fas fa-check" aria-hidden="true"></em>';
console.log(this.params);
this.eGui.appendChild(this.eButton);
};
ClickableStatusBarComponent.prototype.getGui = function()
{
return this.eGui;
};
ClickableStatusBarComponent.prototype.destroy = function()
{
this.eButton.removeEventListener("click", this.buttonListener);
};
ClickableStatusBarComponent.prototype.onButtonClicked = function()
{
getSelectedRows();
};
Here is the code to loop through and find all open detail grids:
function getSelectedRows()
{
this.gridOptions.api.forEachDetailGridInfo(function(detailGridApi) {
console.log(detailGridApi.id);
});
I was able to work this out, so thought I'd post my answer in case others have the same issue. I'm not sure I took the best approach, but it's seemingly working as I need.
First, I also tried using a custom detail cell renderer, as per the documentation, but ultimately had the same issue. I was able to retrieve the DetailGridID in the detail onGridReady function--but couldn't figure out how to use that variable elsewhere.
So I went back to the code posted above, and when the button was clicked, I do a jquery .closest to find the nearest div with a row-id attribute (which represents the the DetailgridID), then I use that specific ID to get the rows selected in just that detail grid.
Updated button click code:
ClickableStatusBarComponent.prototype.onButtonClicked = function()
{
getSelectedRows(this);
};
Updated getSelectedRow function:
function getSelectedRows(clickedBtn)
{
var detailGridID = $(clickedBtn.eButton).closest('div[row-id]').attr('row-id');
var detailGridInfo = gridOptions.api.getDetailGridInfo(detailGridID);
const selectedNodes = detailGridInfo.api.getSelectedNodes()
const selectedData = selectedNodes.map( function(node) { return node.data })
const selectedDataStringPresentation = selectedData.map( function(node) {return node.UniqueID}).join(', ')
console.log(selectedDataStringPresentation);
}
In our project, there are different urls assigned to different categories of product. If the product category is Cat1, click on edit button should take the user to the Cat1 page, and Cat2 should take the user to Cat2 page. However these categories are in a dynamic table so we can not use a fix reference for the edit buttons, and I am trying to make it dynamic. Below is my code snippet:
it('should take the user to appropriate page', function () {
expect(globalVariables.Edit_Button_1.isDisplayed());
// get rows
var row_1 = globalVariables.tableData_Dashboard.all(by.tagName("tr")).get(1);
// get cell values
var cells = row_1.all(by.tagName("td"));
var Cetegory = cells.get(3).getText().then(function (GL) {
// console.log(GL)
return GL;
});
globalVariables.Edit_Button_1.click();
browser.wait(EC.invisibilityOf(globalVariables.Edit_Button_1), 25000, 'Edit button is not disappearing yet');
if (Cetegory.endsWith('Cat1')){
expect(browser.getCurrentUrl()).toEndWith("Cat1");
}
else {
expect(browser.getCurrentUrl()).toEndWith("Cat2")
}
The tests fails with the log " Failed: Cetegories.endsWith is not a function ..
How can this be fixed?
Cetegory is a promise, not a string. Thus it does has function endsWith. You need to consume the promise eventual value in then() as following.
Cetegory.then(function(_Cetegory){
if (_Cetegory.endsWith('Cat1')){
expect(browser.getCurrentUrl()).toEndWith("Cat1");
}
else {
expect(browser.getCurrentUrl()).toEndWith("Cat2")
}
})
So the problem I'm getting is probably something so, so simple (probably), but it's infuriating my as to why it won't work.
What I'd like to do is click on an Edit button on a website, change a value, and Save it.
However, there are over 120 of these changes to be made, and thus over 120 edit clicks, etc.
Hence why I thought I'd use a Data Table.
And here is my subsequent test code;
const { client } = require('nightwatch-cucumber')
const { defineSupportCode } = require('cucumber')
const globals = require('../../config/globals.js')
var emailEntry = (`input[name='administrator[email]']`)
var passwordEntry = (`input[name='administrator[password]']`)
var existingGtmKey = ("GTM-123456")
var newGtmKey = ("GTM-654321")
var gtmKey = (`//div/input[#value='${existingGtmKey}']`)
var saveButton = (`input[type=submit][value='Save']`)
defineSupportCode(({ Given, Then, When }) => {
Given(/^I've logged into Winit cms$/, () => {
return client
.url('http://winit-stage.bauerpublishing.com/admin/sign_in')
.waitForElementVisible('body', 5000)
// Enter winit email address
.moveToElement(`form#new_administrator ${emailEntry}`, 1,1)
.click(`form#new_administrator ${emailEntry}`)
.setValue(`${emailEntry}`, "*****.*****#*****.co.uk")
// Enter winit password
.moveToElement(`form#new_administrator ${passwordEntry}`, 1,1)
.click(`form#new_administrator ${passwordEntry}`)
.setValue(`${passwordEntry}`, "******")
// Click on the 'Sign in' button
.click("form#new_administrator input[type=submit][value='Sign in']")
})
Then (/^I'm able to change the gtm tag for that site (.*?)$/,
(siteedit) => {
return client
// Click on the 'sites' link
.useXpath()
.click("//a[normalize-space(text())='Sites']")
// Click on Edit button
.click(siteedit)
.click(`${gtmKey}`)
.clearValue(`${gtmKey}`)
// Set new gtm key value
.setValue(`${gtmKey}`, `${newGtmKey}`)
// Click save
.useCss()
.click(`${saveButton}`)
})
})
I thought (wrongly!) this would be pretty straightforward, the script would log into my account, click the edit button, enter new value, press the save key, then do the same for the next website edit button.
It works for the first edit button in the Data table, but then the test fails, giving the following error;
So it looks as though it's running the whole script, and not just the Then part of the script.
But I don't understand why??
Any help would be greatly appreciated.
Many thanks.
I am trying to build an SAPUI5 application using TreeTable and I'm facing some problems to use its methods.
In my app, I have a button which triggers this method.
onChangeViewContext: function(oEvent) {
.........
.........
var aViewContext = oContext.oModel.getProperty(sPath + "/ViewContext");
var aDataModel = oContext.oModel.getProperty("/ApplicationCollection/" + sAppId + "/DataModel");
var oStructure = this._createParentChildStructure(aDataModel);
var oTreeModel = this.getView().getModel("treeModel");
oTreeModel.setData(oStructure);
this._oViewDetailLine = oSource.getParent().getParent().getParent();
this._oViewDetailLine.setVisible(false);
this.byId("idSelectElementsPanel").setVisible(true);
this._setSelectedItems(aViewContext, oTree);
}
What I'm trying to do here is only bind the rows with my treeModel, get tree table object and send it to my _setSelectedItems method which below.
_setSelectedItems: function(aViewContext, oTree) {
oTree.clearSelection();
var sElementName;
var aSelectedIndices = [];
var aElements = [];
var aRows = oTree.getRows();
aRows.forEach(function(row) {
if (row._oNodeState !== undefined) {
aElements.push(row.getCells()[0].getText());
}
});
I need to get rows array here because I will use it for setting selected items of tree table. The problem is when "onChangeViewContext" triggered, oTable.getRows() returns an empty array. But when I click cancel button (which just hides my tree table, nothing more) and then trigger "onChangeViewContext" function again, I can get the rows array completely.
Even on the first call when I try to get table's model, I can get the treeModel and its data correctly.
I've tried to refresh bindings, aggregations etc. But no luck.
By the way, I'm using row binding in my xml view like this :
<t:TreeTable id="idSelectElementsTree" rows="{path: 'treeModel>/'}" selectionMode="MultiToggle" enableSelectAll="false"
rowSelectionChange="onSelectElement">
I'm really drowning here so any any help would be appreciated.
Edit : rest of the setSelectedIndexes function :
aViewContext.forEach(function(name) {
sElementName = name;
if (aElements.indexOf(sElementName) !== -1) {
aSelectedIndices.push(aElements.indexOf(sElementName));
}
});
aSelectedIndices.forEach(function(idx) {
if (oTree.getRows()[idx]._bHasChildren) {
oTree.expand(idx);
}
oTree.addSelectionInterval(idx, idx);
});
What could help here is to add an event rowsUpdated="onRowsUpdated" to the table in the XML view. This event is triggered after the table has been loaded and will hence provide you with the data via;
this.getView().byId("sTableId").getRows();
The difference to your approach is that the event would not be triggered by the press of a button but automatically, as the table is rendered. You can then also use this function to trigger another one as per your use case.
I have a webgrid that gets populated on page load. In this grid I have an element that has a javascript event handled when it is clicked. Here I simply intend to sent the user to an external site. I also have this tied to a controller. Both are working for the first element. However, when it comes to anything after the first element in the list the javascript does not get called.
WebGrid:
#grid.GetHtml(tableStyle: "table table-striped table-bordered",
headerStyle: "thead-default",
columns: grid.Columns(
grid.Column("post_tran_a", Model.year_a, canSort: false, format: (item) =>
new HtmlString(Html.CheckBox("post_tran_a", (bool)item.post_tran_a.is_reviewed, new { disabled = "disabled" })
+ " " +
Html.ActionLink((string)item.post_tran_a.month, "PostTransmission", Model.controller, new { report_id = item.post_tran_a.report_id, link = item.post_tran_a.link }, new { #id = "external-link", data_url=Url.Action() })
))))
Javascript:
$("#external-link").click(function () {
var url = $("#external-link").attr("data-url");
alert(url);
});
If this approach won't work I'm open to alternative solutions.
Simplest way in your particular case might work like
$("table a").click(function () {
// you need here 'this' it is available by default
// and it points to the object on which click is called
var url = $(this).attr("data-url");
alert(url);
});
But above is too general. It will fail if you have tables having other links a where you do not want to fire the even so better approach is following
Id only works for one element. For a set of elements (e.g. multiple links). You need to use the class and access them by class as well.
I replaced your id with class and accessed it with that name as well.
grid.GetHtml(tableStyle: "table table-striped table-bordered",
headerStyle: "thead-default",
columns: grid.Columns(
grid.Column("post_tran_a", Model.year_a, canSort: false, format: (item) =>
new HtmlString(Html.CheckBox("post_tran_a",
(bool)item.post_tran_a.is_reviewed, new { disabled = "disabled" })
+ " " +
Html.ActionLink((string)item.post_tran_a.month, "PostTransmission",
Model.controller, new { report_id = item.post_tran_a.report_id, link = item.post_tran_a.link },
// See following carefully
new { #class="someuniquecalssname" data_url=Url.Action() })))))
Now the javascript will work fine
$(".someuniquecalssname").click(function () {
var url = $(this).attr("data-url");
alert(url);
});
If you are not willing to add class attribute then, Creating Unique Ids like ex-link1, ex-link2 could be possible in many cases. But they are useless for an event like above
You are using id to select the element, an id must be unique on the page. use either a class or unique ids when setting them in your code #id = "external-link--xxx"
You could also use a different selector in your jquery selector
$("#yourtableid a").click(function () {
var url = $("#external-link").attr("data-url");
alert(url);
});