Send dynamic Grails g:select values to JavaScript - javascript

I need help trying to get the values from a g:select statement and passing them into a JavaScript function.
So far I have the button
<a href='javascript:void(0)' onclick='runReport("${reportInstance.name}")'>Run Report</a>
Which calls a .js file with
function runReport(reportIn){
var url = reportViewerPath + reportDirectory + reportIn + reportSuffix + promptChain;
window.open(url,'Report Viewer','fullscreen=yes,menubar=yes,status=yes');
}
And this works great. Now the challenge is we have g:select statements on the main .gsp page, but they are variable in number. There could none, or there could be 20, it just depends on the report chosen by the end user.
<g:select id="${prompt.name}" from="${listPromptValues[prompt.name]*.values().collect()}" name="prompt" value="" noSelection="['':'']"/>
This generates the drop down menu with the values for what ever prompt there is.
How do I grab ${prompt.name} and the selected value for every prompt on the page, and then pass that to the .js file as well?
Ideally when runReport() is called, it will pass the reportName, and the prompts will get passed as
&Phone=867-5309&City=NewYork&Name=Jenny
Each url variable would be an optional g:select, so it could also be
&City=NewYork&Name=Jenny
I feel like something like this Related Stack Overflow question would be on the right track.
var prompts = "";
$('$prompt.name').change(function() {
prompts += $(this).text();
$("a").attr('href', function(i, h) {
return h + (h.indexOf('?') != -1 ? "&" : "?") + "selectValue="+val;
});
});
However prompts would have to be a global so that it isn't overwritten every time there is a change.
Edit: Here is the DOM object on the .gsp page
<div id="runButton">
<g:form controller="report">
<g:if test="${reportInstance?.id}">
<a href='javascript:void(0)' onclick='runReport("${reportInstance.name}")'>Run Report</a>
</g:if>
</g:form>
</div>
<ol class="property-list report">
<g:if test="${reportInstance?.prompts}">
<hr>
<li class="fieldcontain" id="prompt">
<g:each var="prompt" in="${reportInstance.prompts}">
<span id="prompts-label" class="property-label">
<g:message code="report.prompts.label" default="${prompt.description}:" />
</span>
<g:if test="${prompt.datatype.type == 'DropDown'}">
<g:select id="${prompt.name}" from="${listPromptValues[prompt.name]*.values().collect()}" name="prompt" value="" noSelection="['':'']"/>
<br>
</g:if>
</g:each>
</li>
</g:if>
</ol>
And then in run.js
function runReport(reportIn){
var promptChain = $("#prompt :select[name=prompt]").serialize();
reportName = reportIn;
...
}
Am I going about this incorrectly?
Edit 2: Grabbing the prompts like it should
...
<g:if test="${prompt.datatype.type == 'DropDown'}">
<g:select id="${prompt.name}" from="${listPromptValues[prompt.name]*.values().collect()}" name="${prompt.name }" value="" noSelection="['':'']"/>
<br>
</g:if>
...
and the jQuery
var promptChain = jQuery('select').serialize();

You're using jQuery, so just serialize the form's select elements. Doesn't matter how many their are. No need to track some global variable.
function runReport(reportIn) {
var promptChain = $("select[name=prompt]").serialize();
....
}
Here's a jsFiddle

Related

how to remove data from chiptagBody in javascript

I am not able delete the data from ChipTagBody.removeAuditPeriod() is getting called properly but data still showing in UI.
<c:set var="idRow" value="${auditPeriod.auditPeriodId}" />
<span id=Period'+idRow+' class="ChipTagBody"><span class="ChipTagContent"><a onclick="removeAuditPeriod(idRow)" class="ChipTagClose" role="presentation">×</a><c:out value="${auditPeriod.auditPeriodFrom} - ${auditPeriod.auditPeriodTo}"></c:out></span></span>
function removeAuditPeriod(idRow) {
auditPeriodId = null;
$('#' + 'Period' + idRow).remove();
}
Your ID Attribute seems to be malformed.
<span id=Period'+idRow+'> doesn't look right.
It should probably be something like <span id="Period${idRow}"> right?

Dynamic attribute value element locator in Protractor

When I add a new button with some value it gets dynamically added into DOM. Non-Angular HTML element for this button is:
<li class="ui-state-default droppable ui-sortable-handle" id="element_98" data-value="2519">
25.19 EUR
<button type="button" class="btn btn-default removeParent">
<span class="glyphicon glyphicon-remove" aria-hidden="true">
</span>
</button>
</li>
Once I remove this button I want to check it is not present anymore. Element that I'm searching for is data-value="2519"and this could be anything I set, like for example 2000, 1000, 500, 1050,...
In page object file I have tried to use the following:
this.newValueButtonIsNotPresent = function(item) {
newValueButton = browser.element(by.id("containerQUICK_ADD_POINTS")).all(by.css('[data-value="' + item + '"]'));
return newValueButton.not.isPresent();
};
And in spec file I call this function as follows:
var twentyEurosButtonAttributeValue = '2000';
describe("....
it ("...
expect(predefined.newValueButtonIsNotPresent(twentyEurosButtonAttributeValue)).toBeTruthy();
I know this is not correct, but how I can achieve something like that or is there another way?
Stupid me, I found a simple solution. Instead dynamically locating an element I located the first on the list, which is always the one, which was newly added and then checked if it's text does not match:
Page object file:
this.newValueButtonIsNotPresent = function() {
newValueButton = browser.element(by.id("containerQUICK_ADD_POINTS")).all(by.tagName('li')).first();
return newValueButton.getText();
};
Spec file:
// verify element 20.00 EUR is not present
predefined.newValueButtonIsNotPresent().then(function(value) {
expect(value).not.toEqual(twentyEurosText);
});

how to access value of dynamic generated model in angular

<input type='text' ng-model='album"+$scope.i+"' />
<h1> {{album+i}} </h1>
I am setting the value of i in controlller and when I inspect the textbox,
ng-model="album1" is reflected or whatever the value of i.
But now on button click in I am in need to pass this model value to some function.
Can somebody let me know, how to access this dynamic model value?
I did following patterns to access the model value:-
{{album+i}}
{{'album'+i}}
{{album"+i+"}}
But none of this, is reflecting this value.
Note: this textbox+button is appened dyanmically and I have compiled textbox+button and on ng-click required function is called as well, only model value is not getting reflected.
$scope.appendAlbum = function()
{
$scope.i = $scope.i + 1;
var tplAlbum = "<ul class='cols'> \
<li class='col-md-2'>\
<input type='text' ng-model='album"+$scope.i+"' required /></li>\
<li>\
<a href='javascript:void(0)' ng-click='saveAlbum(album+$scope.i)' class='saveBtn' title='Click to save'> </a>\
</li>
</ul>";
angular.element(document.getElementById('albumCols')).append(tplAlbum);
var eleScope = $('#albumCols .cols:last').scope();
$compile($('#albumCols .cols:last'))(eleScope);
}
Use ng-model='album{{$scope.i}}' and ng-click='saveAlbum(album{{$scope.i}})'
Update ng-click to this, will do the trick
<a href='javascript:void(0)' ng-click='saveAlbum(album"+$scope.i+")'> </a>\
saveAlbum(album"+$scope.i+")

Update unrelated field when clicking Angular checkbox

I have a list of checkboxes for people, and I need to trigger an event that will display information about each person selected in another area of the view. I am getting the event to run in my controller and updating the array of staff information. However, the view is not updated with this information. I think this is probably some kind of scope issue, but cannot find anything that works. I have tried adding a $watch, my code seems to think that is already running. I have also tried adding a directive, but nothing in there seems to make this work any better. I am very, very new to Angular and do not know where to look for help on this.
My view includes the following:
<div data-ng-controller="staffController as staffCtrl" id="providerList" class="scrollDiv">
<fieldset>
<p data-ng-repeat="person in staffCtrl.persons">
<input type="checkbox" name="selectedPersons" value="{{ physician.StaffNumber }}" data-ng-model="person.isSelected"
data-ng-checked="isSelected(person.StaffNumber)" data-ng-change="staffCtrl.toggleSelection(person.StaffNumber)" />
{{ person.LastName }}, {{ person.FirstName }}<br />
</p>
</fieldset>
</div>
<div data-ng-controller="staffController as staffCtrl">
# of items: <span data-ng-bind="staffCtrl.infoList.length"></span>
<ul>
<li data-ng-repeat="info in staffCtrl.infoList">
<span data-ng-bind="info.staffInfoItem1"></span>
</li>
</ul>
</div>
My controller includes the following:
function getStaffInfo(staffId, date) {
staffService.getStaffInfoById(staffId)
.then(success)
.catch(failed);
function success(data) {
if (!self.infoList.length > 0) {
self.infoList = [];
}
var staffItems = { staffId: staffNumber, info: data };
self.infoList.push(staffItems);
}
function failed(err) {
self.errorMessage = err;
}
}
self.toggleSelection = function toggleSelection(staffId) {
var idx = self.selectedStaff.indexOf(staffId);
// is currently selected
if (idx >= 0) {
self.selectedStaff.splice(idx, 1);
removeInfoForStaff(staffId);
} else {
self.selectedStaff.push(staffId);
getStaffInfo(staffId);
}
};
Thanks in advance!!
In the code you posted, there are two main problems. One in the template, and one in the controller logic.
Your template is the following :
<div data-ng-controller="staffController as staffCtrl" id="providerList" class="scrollDiv">
<!-- ngRepeat where you select the persons -->
</div>
<div data-ng-controller="staffController as staffCtrl">
<!-- ngRepeat where you show persons info -->
</div>
Here, you declared twice the controller, therefore, you have two instances of it. When you select the persons, you are storing the info in the data structures of the first instance. But the part of the view that displays the infos is working with other instances of the data structures, that are undefined or empty. The controller should be declared on a parent element of the two divs.
The second mistake is the following :
if (!self.infoList.length > 0) {
self.infoList = [];
}
You probably meant :
if (!self.infoList) {
self.infoList = [];
}
which could be rewrited as :
self.infoList = self.infoList || [];

Can't check checkboxes after passing parameter - grails / javascript / facebox

I'm doing some ajax requests in Grails 1.3.7. The front end uses jQuery and the 'facebox' plugin.
After a successful request and response, I redirect back to the page with a 'confirm' param which is picked up by javascript.
The facebox plugin works fine on its own, but when I pass the 'confirm' parameter, the facebox popup works, but the checkboxes on the popup are unclickable (they aren't disabled, the arrow just doesn't show up when you click them). This was tested in Chrome and FF. I thought it might be a duplicate ID issue, but I made sure the checkbox and IDs were unique.
Any ideas? Or is there a better way to do this?
Grails action:
def deleteEmailRecipient = {
def recipientId = params.id
accountService.deleteEmailRecipient(recipientId)
redirect(action:'settings', params:[confirm:1])
}
JS:
$(document).ready(function() {
//get params to display save confirm if confirm detected
var url = window.location.toString();
url.match(/\?(.+)$/);
var params = RegExp.$1;
var splitParams = params.split("&");
for (var i=0;i<splitParams.length;i++) {
var tmp = splitParams[i].split("=");
if (tmp[0] == 'confirm') {
$.facebox({div: '#addWord'});
}
}
});
GSP (that shows up in facebox):
<div class="checkboxes" style="border: 1px solid #FFFFFF;">
<g:each in="${wordGroups}" var="wg" status="i">
<label class="category">
<g:checkBox name="${wg.id}"/>
<span style="font-weight:bold;margin-right:5px;white-space: nowrap;">
<img class="dropdownFlag" src="${resource(dir:'images',file:icon)}" alt="" />${wg.name}
</span>${(i+1)%4 == 0 ? '<br />' : ''}
</label>
</g:each>
</div>

Categories