Passing AngularJS object to JSF-call - angularjs

I'm using AngularFaces and I want to pass an Angular JS object to an JSF bean method.
I'm iterating over a table and want to put specific buttons for every iteration:
<table ng-table="tableParams">
<tr ng-repeat="user in $data">
<td data-title="'User id'">{{user.id}}</td>
<td data-title="'Name'">{{user.name}}</td>
<td data-title="'Hide User'">
<p:commandButton value="Hide" id="hideUser" action="#{bean.hideUser({{user.id}})}"">
<f:param name="myId" value="{{disponent.dispNr}}" />
</p:commandButton>
</td>
</tr>
</table>
The important line is:
<p:commandButton value="Hide" id="hideUser" action="#{bean.hideUser({{user.id}})}">
I tried several ways, e.g.
<p:commandButton value="Hide" id="hideUser" action="#{bean.hideUser(user.id)}">
But nothings works. How can I achieve this?

Passing an AngularJS object to JSF caused me a lot of headache, too. After a while I've found a solution, but I'm still not happy with it. I hope to find a better solution in one of the next versions of AngularFaces.
As for now, you can use the global function afToJson to serialise the AngularJS object and pass it to JSF as a string:
<button class="carFilterButton" jsf:action="#{selectionBean.showDetails()}"
ng-click="selectionBean.carAsJSon=afToJson(car);">show me!</button>
(see
https://github.com/stephanrauh/AngularFaces/blob/master/AngularFaces_2.0/AngularFaces-2.0-examples/src/main/webapp/carshop/ngtable.xhtml).
On the server side, you can use the JSONUtilites of AngularFaces to deserialize the string back to a regular object:
private String carAsJSon;
private Car car;
public String getCarAsJSon() {
return carAsJSon;
}
public void setCarAsJSon(String carAsJSon) {
this.carAsJSon = carAsJSon;
int pos = carAsJSon.indexOf(",\"$$hashKey\"");
if (pos > 0)
carAsJSon = carAsJSon.substring(0, pos) + "}";
Car car = (Car) JSONUtilities.readObjectFromJSONString(carAsJSon, Car.class);
return getCarBean().showDetails(car);
}
(see https://github.com/stephanrauh/AngularFaces/blob/master/AngularFaces_2.0/AngularFaces-2.0-examples/src/main/java/de/beyondjava/jsf/sample/carshop/SelectionBean.java).

Related

How to add a new record and not update previous record in angularjs

How do I add a new record and have angular "forget" the new item added after I click the corresponding button.
The ability to add a record works and when I add the new record it display in the table I have, correctly, However my problem is that when I go to add a second record ie I remove the previous input and type something else. This results in the newly added record below to also change.
In short after I add an item to my array I want angular to forget it. How do I accomplish this.
In my controller I have this
(function () {
var app = angular.module("mainApp");
var ordersController = function ($scope,$filter, ordersService,customerService) {
$scope.orders = [];
$scope.addOrder = function (newOrder) {
$scope.orders.push(newOrder);
}
app.controller("ordersController", ["$scope","$filter", "ordersService","customerService", ordersController]);
}());
in my html I have this
<div><table>
<tr>
<td><input ng-model="item.quantity" type="text" /></td>
<td><button type="button" ng-click="addOrder(item)">Add Line Item</button></td>
</tr>
</table></div>
<div>
<table>
<tr ng-repeat="order in orders track by $index">
<td>
{{ order.quantity }}
</td>
</tr>
</table>
</div>
The problem might be that you are adding the newOrder object to the array while Angular keeps it's model bound to that object. Try using Angular's copy functionality like this (assuming that you are using Angular 1):
$scope.addOrder = function (newOrder) {
var copiedOrder = angular.copy(newOrder);
$scope.orders.push(copiedOrder);
}
The documentation for the copy method can be found here.

ui.bootstrap.collapse - one collapse for each row in a table column - open only the collapse which has been clicked (not all of them)

I'm using ui-bootstrap.collapse inside a table with dynamic data from a JSON API. Two of the multiple columns contain collapsed partials for each of its rows.
When I'm clicking on one of the icons to toggle that particular partial, every partial of the entire column open up.
Same issue when I'm trying to close the partial again - any of the icons work (not only the one of that particular partial).
I'm suspecting that I got to add a unique id or something like this to each of the partials to make one only that particular one pop up. But I'm not able to get this working.
Can any one point me in the right direction please?
Here is some of my code (I replaced the dynamic data with static data to make it simpler:
...
<tbody ng-repeat="url in urls">
<tr>
<td>{{url.url}}<span class="pull-right" ng-click="toggleUrl()">▼</span></td>
<td>{{url.title}}</td>
<td>{{url.traffic}}<span class="pull-right" ng-click="toggleTraffic()">▼</span></td>
</tr>
<!-- urlCollapsed -->
<tr collapse="!urlCollapsed">
<td colspan="4" style="background-color: pink">
</td>
</tr>
...
and a working plunker with the entire code: http://plnkr.co/edit/e4UldAFjjIr26Il73C88?p=preview
You need to pass url or some unique field to toggleUrl() method and then at the method make specific variable for each roe partial nd make them true. Accordingly you'll have to mak specific partial for each nd shoe them accordingly on ng-show.
Something like this
$scope.toggleUrl = function (url) {
if (url === '/1') {
$scope.url1Collapsed = !$scope.url1Collapsed;
} else {
$scope.urlCollapsed = !$scope.urlCollapsed;
}
};
and on page
<tr collapse="!url1Collapsed">
<td colspan="4" style="background-color: pink">partial 1</td>
</tr>
<tr collapse="!urlCollapsed">
<td colspan="4" style="background-color: pink"> partial 0</td>
</tr>

nested (double) loop with thymeleaf

I've tried searching for existing answers, but I could not find them.
I'd like to access an ArrayList from an object within an ArrayList, so:
Basically two classes: Glossary and Word.
Glossary contains a list with Word objects, the class Word contains a list with more Word objects (related words)
<table>
<span th:each="word : ${glossary.words}">
<td>
<tr th:each="relatedWord: ${word.relatedWords}">
<p th:text="${relatedWord.getName()}"></p>
</tr>
<td>
</span>
</table>
Unfortunately this does not work for me..
I'm not sure but I don't think you can access public non-static getters like you do (assuming getName() is marked as public).
You should try:
<table>
<span th:each="word : ${glossary.words}">
<td>
<tr th:each="relatedWord: ${word.relatedWords}">
<p th:text="${relatedWord.name}"></p>
</tr>
<td>
</span>
</table>
One note: the above code is absolutely not valid XHTML (span directly inside table, tr directly inside td).

How to get Angular to update the Ui from within the controller

I have the following html.
<div ng-controller="CustCtrl">
<table class="table table-condensed">
<thead>
etc.
</thead>
<tbody>
<tr ng-repeat="customer in customers" data-cust-id="{{customer.Id}}">
<td>
<button ng-model="Id" tracking-{{customer.Tracking}} ng-click="startTrackingCustById(customer.Id)">
</button>
</td>
etc.
</tr>
</tbody>
</table>
So the button has a class that is databound to the customer.Tracking value which is either true or false. When the button is clicked the startTrackingCustById() method is successfully called and the customer object in the customers object is successfully changed like customer.Tracking = true.
But the buttons class is not updated. What am I missing?
Look at using ng-class . For a boolean value in scope you would use:
ng-class="{'classNameToAddIfTrue':customer.Tracking}"
In the CustCtrl I wrapped the call that updated the customers array like this
$scope.$apply($scope.customers[i].Tracking = true);
Based on the suggestion in an answer I will link to when I find it that basically said "If you are having trouble updating the view you most likely need to use $scope.$apply
So that get's it to work. Now I need to figure out why and how.

ICEfaces: How to pass parameters from one page to another

I have this simple scenario which doesn't work: I use icefaces and i have a simple page with some inputTexts and a submit button, this button will redirect to another page that will display the values of these inputTexts... my question is how can i get the values of these inputTexts from the request and display them in another page?
When i use the following API in the other page backbean, i get only the name of the page that holds the inputTexts:
FacesContext.getCurrentInstance().getExternalContext().getRequestMap();
I really did spent alot of time trying to get this thing to work, so any help will be appreciated.. THx
my page code is:
<ice:form id="form1">
<table border="0">
<tbody>
<tr>
<td><ice:outputText value="Name"></ice:outputText><br></br></td>
<td><ice:inputText id="name" value="#{newContest.name}"></ice:inputText></td>
</tr>
<tr>
<td><ice:outputText value="End Date"></ice:outputText></td>
<td><ice:inputText id="endDate" value="#{newContest.endDate}"></ice:inputText></td>
</tr>
<tr>
<td><ice:outputText value="private? (only you can see the entries)"></ice:outputText></td>
<td><ice:inputText id="private" value="#{newContest.isPublic}"></ice:inputText></td>
</tr>
<tr>
<td><ice:outputText value="Price"></ice:outputText></td>
<td><ice:inputText id="price" value="#{newContest.price}"></ice:inputText></td>
</tr>
<tr>
<td><ice:outputText value="Description"></ice:outputText></td>
<td><ice:inputTextarea id="description" value="#{newContest.description}"></ice:inputTextarea></td>
</tr>
<tr>
<td><br></br><ice:commandButton value="proceed to payment" style="color:blue" action="#{newContest.createContest}"></ice:commandButton></td>
</tr>
</tbody>
</table>
You can bind another bean with current one as a managed property in faces-config.xml as follows.
<managed-bean>
<managed-bean-name>newContest</managed-bean-name>
<managed-bean-class>com.newContest</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>anotherBackingBean</property-name>
<property-class>com.AnotherBackingBean</property-class>
<value>#{anotherBackingBean}</value>
</managed-property>
</managed-bean>
<navigation-rule>
<navigation-case>
<from-outcome>view-anotherBackingBean</from-outcome>
<to-view-id>/jsp/another-page.jspx</to-view-id>
</navigation-case>
</navigation-rule>
Bean Content
Class NewContest {
public AnotherBackingBean anotherBackingBean;
//-- set/get & other methods
public String redirectToAnotherBackingBean(){
anotherBackingBean.setSomeObject(object);
//-- set custom fields
return "view-anotherBackingBean";
}
}
Then you can get your fields directly available in other bean which have been set in current bean.

Resources