Basically, I want to implement a webpage using Primefaces line chart that can change every one second.
In my managed bean, I get, say 100 data from my database. Instead of populating the line chart all at once, I want to display them like a data wave, so that these 100 data can be shown in 100 seconds.
How can I implement this?
You should get 100 data from DB and store them in a list let say main list, and there should be one more list which will be refreshed every one second and the current element of main list will be appended to second list . Sth. like that:
#ManagedBean
#ViewScoped
public class DataBean {
private ArrayList<Data> mainList;//fill this from DB via seperate DAO class
private ArrayList<Data> viewList;
public int counter;
//getter and setters
public void refreshList() {
viewList.add(mainList.get(counter);
counter++;
}
}
And at the view layer you should call refreshList method periodically of course this can be done with p:poll or p:remoteCommand. RemoteCommand needs to be called more than once via JS code, it's like:
jQuery(document).ready(function () {
setInterval("updateChart", 1000);//every 1 sec
});
And this func. will call the p:remoteCommand which is named as updateChart:
<p:remoteCommand name="updateChart" actionListener="#{dataBean.refreshList}"
update="myChart"/>
myChart is the client id of your p:lineChart component you have to give the exact ID, you can detect it via your browser's developer settings.
And remember that this is not the exact implementation there can be errors, and p:lineChart expects model classes instead arrayLists, I've never used chart components but I'm assuming series similar to lists. Hope this can guide you.
Related
I have this really complicated form. All the fields must be filled, but the process of filling can be saved and leter continued. So what i need s that when finally confirm is pressed, all the data get validated. But because it is already saved to database calling validate() wont work. I save the data by douing save(validate:false), because i dont need validation when the work is still in progremm.
How can i validate data that has already been saved to database ? Do i have to do it manually?
What happens when you validate an already persisted object?
Is there a way to make it appear dirty after retrieving and before validating?
I have edited the answer to explain form encapsulation in more detail, typically maybe from a tier step process of form input or more complex iterated objects that needs to be elsewhere. To begin if all you need is a one step that captures a variety of information and you are happy to then process all that manually and store in different classes on mass params dump then look into jquery-ui tabs. If you choose to use the dynamic feature of tabs i.e. <li><a href="someurl">click</li> which then loads content dynamically to a given tab then that would also cover single forms that are outside or maybe if you prefer more complex within DOM.
Anyhow the reason for my edit wasn't above it is for something a little more complex that captures multi tier forms.
So you had step 1 that sent params through to a controller that then passed those params to a new gsp or maybe even an iteration of something that belongs to another totally different object within the form.
Typically you would end up with:
<g:form action=myDomain" action="doThis">
<!-- this is some iteration that belongs to some other class outside of what i am actually trying to do: -->
<g:each in="someObject" var="p">
<g:hiddenField name="form1.firstName" value="${p.firstName}"/>
<!-- in this case hidden -->
<g:hiddenField name="form1.surName" value="${p.surName}"/>
</g:each>
<!-- this is my actual form -->
<g:textField name="username" />
</g:form>
When form is submitted to a controller
Class MyDomainController {
def doThis(MyBean bean) {
save(bean)
}
}
//this be in src/main/groovy
import grails.validation.Validateable
//important for some reason it needs entire collections
// have had issues initialising it without .*
import org.apache.commons.collections.*
Class MyBean implements Validateable {
//this is capturing the current form fields
String username
//This is now collecting our form1 fields
List<MyDetailsBean> form1 = ListUtils.lazyList([], { new MyDetailsBean() } as Factory)
//if that had been 1 instance of it or like as mentioned passed from pervious form and called form2
MyDetailsBean form2
static constraints={
username(nullable:false) //, validator: checkSomething)
}
}
This is again in src/main/groovy and was used to originally collect each iteration of an object:
import grails.validation.Validateable
Class MyDetailsBean implements Validateable {
String firstName
String surName
}
I have updated the answer since i suggested encapsulating the object in a bean without any details of how one would go about doing such a thing. I hope above is clear. It is all on the fly but if tested hope it all works as explained above.
TO add after next update explained form2 example. to finally validate both sets you call
if (bean.validate() && bean.form2.validate()) {
//all good
}
Because you are binding it to another validation class the rules of that class can now be applied as part of validation process.
Old answer
Quite simply put it is on the db why on earth would you want to validate a validated input. Anyhow the work around is a validation bean in Grails 2 src/groovy/package which is #Validateable or
Grails 3 : src/main/groovy/package which implements Validateable
class MyDmainBean {
// must declare id
def id
// Then each object in your real domain class
static constraints = {
id (nullable:true,bindable:true)
importFrom MyDomainClass//, exclude: ['field1']
//field 1 is not included but if field 1 was integer
// in actual domain class and BigDecimal in bean
//then exlude it since it won't bind
}
def formatObject(MyDomainClass domain) {
id=domain.id
..
}
}
Now you can call
MyDomain record = MyDomain.get(0L)
MyDmainBean bean = new MyDmainBean().formatObject(record)
bean.validate()
I've read several posts here and also the tutorials on Telerik website, but they are lacking - and the documentation is off.
Hoping for a quick fix after hours of reading.
I'm trying to use a Kendo grid with a huge amount of rows (1M). In the examples on the site, I see that the view controller action is returning the whole data set.
Fetching all of the rows is very expensive process and the data set is huge.
My question is how can I configure the grid in such a way that every subsequent callback will return the next page and the initial call will not fetch all of rows at once?
My code is similar to:
//Main controller action
public ActionResult Index()
{
List<items> listItems = GetAllItems(); // very expensive call!
return View(listItems);
}
// my view for that action
#(Html.Kendo().Grid(Model)
.Name("grid")
.Columns(columns =>
{
//some columns...
})
.Pageable(page=>page.PageSizes(true)) //Enable paging - I suspect here I can fix
.DataSource(datasource =>datasource.Ajax().PageSize(20).Read(read => read.Action("MoreItems", "Index")).ServerOperation(true)) // tried all sorts of things here
.Sortable()
.Filterable()
)
// the callbacks for the ajax
public ActionResult MoreItems([DataSourceRequest] DataSourceRequest request)
{
return Json(GetAllItems().ToDataSourceResult(request));
}
//add some cache just to see what was holding the thing up
[OutputCache(Duration = 3600, VaryByParam = "none")]
private static List<items> GetAllItems()
{
//some code to retrieve items
}
(from the examples it looks like the initial call is returning the complete model - and subsequent calls to the Products_Read are on the filter object. How can the initial call be filtered as well but allow for future paging - in my case I have 100k+ rows and it is impossible to do "return View(model") ) Thanks!
Seems that have not been very lucky with Kendo information... What you are looking for is called serverPaging (documentation under framework DataSource in here).
For each request your server will receive:
take contains the number of records to retrieve
skip how many records from the front of the dataset to begin reading
page the index of the current page of data
pageSize the number of records per page
You might also consider using scrollable.virtual (documentation in here where the following pages are loaded while you scroll down in the grid.
This example (http://demos.kendoui.com/web/grid/remote-data.html) uses serverPaging.
It seems that you are not familiar with the LINQ expression engine. The whole collection is never retrieved. The ToDataSourceResult method is doing exactly this - applying paging/sorting/grouping on a database level (thanks to that expression engine).
You do not have to do anything - just pass the IQueryable collection (which holds all the records) to the DataSourceResult, do not call ToList before this(or anything similar) or the magic will be broken :)
I've been facing a problem that is basically the following:
I have a knockout ViewModel which contains observable arrays of items with observable properties and methods.
I need to pull data from the server. The methods need to exist after data is taken from server. So I create a new ViewModel and then update its value from what comes from server. (THIS DOES NOT WORK, THE RESULTING ARRAY HAS NO ITEMS)
If I create, with mapping, a new object using var newObj = ko.mapping.fromJS(data) the resulting Array has items, but its items have no methods. It spoils my Bindings.
The fiddle of my problem: http://jsfiddle.net/claykaboom/R823a/3/ ( It works util you click in "Load Data From The Server" )
The final question is: What is the best way to have items on the final array without making the loading process too cumbersome, such as iterating through every item and filling item's properties in order to keep the previously declared methods?
Thanks,
I changed your code little bit. Check this version of JSFiddle.
var jsonFromServer = '{"ModuleId":1,"Metadatas":[{"Id":1,"MinValue":null,"MaxValue":null,"FieldName":"Teste","SelectedType":"String","SelectedOptionType":null,"IsRequired":true,"Options":[]}]}';
Your code doesnt work because your jsonFromServer variable does not contain methods we need at binding like you described in your question. ( -- > Metadatas )
So we need to define a custom create function for Metadata objects at the mapping process like this :
var mapping = {
'Metadatas': {
create: function(options) {
var newMetaData = new MetadataViewModel(options.parent);
newMetaData.Id(options.data.id);
newMetaData.FieldName(options.data.FieldName);
newMetaData.SelectedType(options.data.SelectedType);
newMetaData.SelectedOptionType(options.data.SelectedOptionType);
newMetaData.IsRequired(options.data.IsRequired);
newMetaData.Options(options.data.Options);
// You can get current viewModel instance via options.parent
// console.log(options.parent);
return newMetaData;
}
}
}
Then i changed your load function to this :
self.LoadDataFromServer = function() {
var jsonFromServer = '{"ModuleId":1,"Metadatas":[{"Id":1,"MinValue":null,"MaxValue":null,"FieldName":"Teste","SelectedType":"String","SelectedOptionType":null,"IsRequired":true,"Options":[]}]}';
ko.mapping.fromJSON(jsonFromServer, mapping, self);
}
You dont have to declare a new viewModel and call ko.applyBindings again. Assigning the updated mapping to current viewModel is enough. For more information check this link. Look out for customizing object construction part.
The final question is: What is the best way to have items on the final
array without making the loading process too cumbersome, such as
iterating through every item and filling item's properties in order to
keep the previously declared methods?
As far as i know there is no easy way to do this with your object implemantation. Your objects are not simple. They contains both data and functions together. So you need to define custom create function for them. But if you can able to separate this like below then you dont have to customize object construction.
For example seperate the MetadataViewModel to two different object :
--> Metadata : which contains only simple data
--> MetadataViewModel : which contains Metadata observableArray and its Metadata manipulator functions
With this structure you can call ko.mapping.fromJSON(newMetaDataArray , {} , MetadataViewModelInstance.MetadataArray) without defining a custom create function at the mapping process.
I'm fairly new at event driven programming and using MVC so forgive me if this question seems like a non-question.
I'm trying to assign values to my singleton model class (Client). I have 2 options:
I can use the model class constructor to assign to itself like so:
Class Client{
public var name;
public var email;
public function Client(arg_name, arg_email){
this.name = arg_name;
this.email = arg_email;
}
}
I can use the controller to assign my values for me like so:
Class Controller{
public var client:Client = new Client();
public function assign(){
client.name = "booo";
client.email = "blaaah#email.com";
}
}
Which one of these is a better solution? :) The reason why I'm so confused is cause I've seen examples that just pass values to the model class and do #1 (and setting new variables such as [var fullname = fname + lname], yet I know for a fact that it is the controller's job to assign values to the model.
Better is relative.
The second example is what is commonly called "property injection".
Basically the first option is quicker, smaller, and much less code.
The second option is more readable and flexible.
Regardless of the Controller, injection has the benefit that you can create getters and setters for each property.
So basically you can have something happen such as dispatching an event whenever you change the value of the "name" property.
The flex source code is filled with this concept. For example whenever you change the width of a group, it doesn't just change the value, it performs checks and then sets the group as dirty so that other things can react to it.
Basically it makes it simple to have everything do it's own thing, and it's more Object oriented.
All that doesn't mean that it's actually better, but it is more common now to write code in the second option style.
Hope that helps.
What is the method to refresh data on subsequent pages - second page, third page, etc - of a Primefaces dataTable using the LazyDataModel method?
Also, if I select an item in a dataTable to view its detail on another page, then came back to the dataTable using either the browser's Back button or implement JavaScript's history.back() method, it seems that the dataTable always reset its position to the first page instead of going back to the page the user was on. How can I force the dataTable to stay on the last viewed page?
My codes for lazy loading are:
private final class LazyLoader extends LazyDataModel<BookModel>
{
private static final long serialVersionUID = 1L;
public LazyLoader(String sort, String category, String operator, String input) {
setListing(getBookService().getListing(sort, category, operator, input));
}
#Override
public List<BookModel> load(int first, int pageSize, String sortField, boolean sortOrder, Map<String, String> filters) {
return getListing();
}
}
And for the Submit method is:
public String Submit()
{
sort = sortBean.getSort();
category = categoryBean.getCategory();
operator = operatorBean.getOperator();
input = searchBean.getInput();
lazyModel = new LazyLoader(sort, category, operator, input);
lazyModel.setRowCount(listing.size());
return null;
}
I'm using #ViewScoped for listing the book records as well as showing detail of a book record.
Does anyone has similar issues with Primefaces dataTable?
Keep using #ViewScoped. You should not use #SessionScoped unless you have real needs for it.
To remember the last page, you have to set the first attribute of the load method. You can do that with request parameters. Something like: yourview.xhtml?f=3 .
About the refreshing, the thing is that you are using a lazy loader but you're loading everything at once... Your load method is the one that should do the query on demand, that is, page by page.
Does pagination work for you without lazy loading? I would verify that works as expected before you jump into the hardest case.
If you want your dataTable to remember the last pagination after you navigate away from the JSF page then you need to make your managed bean SessionScoped. The lifecycle of the ViewScoped managed bean ends after navigation leaves the view.
In order to keep the selected page you have to do 2 things.
First make the managedBean session scoped.
Second set a binding between the datatable and a UIData object. In your backend bean for example put
private UIData filasUIData = null;
public UIData getFilasUIData() {
return filasUIData;
}
public void setFilasUIData(UIData filasUIData) {
this.filasUIData = filasUIData;
}
Now in your data table
<ice:dataTable
binding="#{yourBean.filasUIData}"
that´s all.