Normally with Rails, I'd use will_paginate and call it a day, but I'm using Rails5 purely as an API, and front-end is completely Angular2.
I've looked into NG Bootstrap4's Pagination but I'm having quite a few issues getting it to do anything besides render - And I can imagine why. What is the proper process for Paginating on Angular? I tried using will-paging to paginate the JSON but instead I just limit the results.
I also looked into ng2-pagination which seemed to have a lot of the features I wanted, but I started getting
Uncaught TypeError: ctorParameters.map is not a function errors for everything so I thought maybe I should take it a step back.
Would the proper process be to use the controller in Rails to append a 'page' parameter to the JSON Results? Or would something more like Virtualization be the route I should go?
Having quite a few issues - Even once I have the bar active, it obviously can't control my script.
getDecks(): Observable<Deck[]> {
return this.http.get(this.decksUrl)
.map((response: Response) => <Deck[]>response.json())
.catch(this.handleError);
}
this is the call that contacts the API and gets the response - I feel like I would involve the 'page' here to actually allow Pagination to do something?
I was able to figure it out - multiple issues. For those wondering:
Uncaught TypeError: ctorParameters.map is not a function seems to be a compilation issue with newer packages.
Different library but similar issues
I upgraded Ang2 + Respective libraries to remove error. From there the instructions made a lot more sense.
The pipe should be built directly into your ngFor
<span *ngFor="let deck of decks| paginate: { itemsPerPage: 10, currentPage: p }" class="list-group-item list-group-item-action">
Then placing
<pagination-controls (pageChange)="p = $event"></pagination-controls>
Where-ever you want an async bar resolves the issue.
Works perfectly - Library is Ng2-Pagination
Related
I am attempting to build a small proof-of-concept web application using the web2py framework. I'm so close, but my basic lack of knowledge of what's going on means I'm just hacking at it with pure guesswork rather than understanding what's going on. I was hoping someone on here could explain where I am going wrong...
The functionality I'm after is that the data needed to create the draggable items is held in a database table (and will ultimately form a hierarchy) with as little information held in the HTML as possible.
There's a fair bit of information for just about everything in this stack, so much so that I'm drowning in it, I don't know where to start. I suppose I should begin with what I've got so far...
The HTML:
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
...
<script>
$(document).ready(function(){
$.ajax( {
type: "POST",
url: 'dragndrop.py',
success: function( response ) {
$("#draggable7").html(response);
}
} )
});
</script>
<div id="draggable7"></div>
The dragndrop.py script:
## My main draggable spawner
selected = [row.id for row in db(db.t_user_shop_layouts.id==7).select()]
return ''.join([DIV('draggable'.join(k), _class='draggable ui-widget-content', _snap=".ui-widget-header", _snapMode= "inner", _grid= [ 80, 80 ], _style='position: relative;') for k in selected])
And, just for completeness, the model web2py script (although the column I'm interested in is the "id" column, which is auto-generated):
db.define_table('t_shop_layout_items',
Field('f_item_display_name_string', type='string', notnull=True,
label=T('Item Display Name String')),
Field('f_item_icon_file', type='upload',
label=T('Item Icon File')),
Field('f_item_parent_id', type='integer',
label=T('Item Parent Id')),
auth.signature,
format='%(f_item_display_name_string)s',
migrate=settings.migrate)
I'm forcing the db call to only pick up one row at the moment (id == 7) just to get the ball rolling, but eventually what I'd like to do is have the (db.id == db.f_item_parent_id) items shown first. Then when double-click, any (db.f_item_parent_id == this.id) children get spawned using helpers. Then I'm going to get an 80x80 grid size target to land on to set shop layout, and save to db. But all this paragraph is for later, I'm just giving you an idea of where I'm going with it.
Finally, some great tutorials that have helped me along the way, but were either not web2py (PHP seems popular for this) or not dynamically spawning (but hard-coded in the HTML, or what-have-you. If I've missed something obvious, please let me know:
An excellent fiddle: http://jsfiddle.net/robertrozas/qLhke/25/ and its stack overflow beginnings Jquery drag drop form hidden value inserting into php mysql
The web2py documentation: http://web2py.com/books/default/chapter/34/11/jquery-and-ajax
OK, hope that's enough! Any help would be appreciated!
In web2py, you do not create .py files and then use them as URLs. Instead, you create functions in controllers and have URLs of the form /appname/controller/function. See the documentation on dispatching. It is also best to use the built-in URL() function to generate URLs. Also, this should probably be a GET request rather than POST.
You might also want to look into web2py's built-in ajax() function as well as Ajax components.
Regarding your data model, if the f_item_parent_id field is a self reference, then you should define it as a reference field (i.e., type='reference t_shop_layout_items').
More generally, before proceeding further, it will probably be very helpful if you read more of the documentation, particularly chapters 4, 5, 11, and possibly 12.
I'm using Capybara 2.1 with Ruby 1.9.3 using the selenium driver (with Minitest and Test Unit) in order to test a web app.
I am struggling with the StaleElementReferenceException problem. I have seen quite a number of discussions on the topic but I haven't been able to find a solution to the issue that I am facing.
So basically, I'm trying to find all pagination elements on my page using this code:
pagination_elements = page.all('.pagination a')
Then I'm doing some assertions on those elements like:
pagination_elements.first.must_have_content('1')
After those assertions, I'm continuing the test by clicking on the Next Page link to make sure that my future first pagination element will be the Previous Page.
To do that I'm retrieving paginations elements again :
new_pagination_elements = page.all('.pagination a')
And the Stale Error is occurring here, because I'm reaching elements that I've already reached. ( Here is the error )
You can see the link states here.
I really have no idea how to make this common test work properly.
Do you have any tips for a better way to reach my pagination elements?
I sometimes have some problem with AJAX intensive pages, in my case this workaround solves it:
begin
...
rescue Selenium::WebDriver::Error::StaleElementReferenceError
sleep 1
retry
end
I saw the main message in the gist is:
Element not found in the cache -
perhaps the page has changed since it was looked up
I have similar case before. There are two solutions:
Add page.reload before checking same stuff in new page, if you have set Capybara.automatic_reload = false in spec_helper
find a special element in new page which previous page doesn't have. This effect is equivalent to wait.
Another method is to use specific selector. For example, instead of
pagination_elements = page.all('.pagination a')
Use
pagination_elements = page.all('#post_123 .pagination a')
Append a unique id area to the selector and you should not meet such problem.
Interesting link about this error and how to fix it : http://stefan.haflidason.com/testing-with-rails-and-capybara-methods-that-wait-method-that-wont/
Apparently, in addition to race conditions, this error also appears due to misused within blocks. For example:
within '.edit_form' do
click '.edit_button'
# The error will appear here if the 'edit_button' is not a
# descendant of the 'edit_form'
end
HAve you tried to use WebDriver directly rather than via Capybara? This woudl potentially give you more control of when to and when to not cache objects.
e.g. (Apologies for the java syntax but should get the idea)
WebElement searchField = driver.findElement(By.CssSelector("input.foo"));
searchField.click();
searchField.sendKeys("foo foo");
System.out.println(searchField.getText());
//Do something elsewhere on the page which causes html to change (e.g. submit form)
.....
....
//This next line would throw stale object
System.out.println(searchField.getText());
//This line will not throw exception
searchField = driver.findElement(By.CssSelector("input.foo"));
System.out.println(searchField.getText());
Assigning "findElement" again to "searchField" means that we re-find the element. Knowing when to and when not re-assign is key went deciding how to cache your webelements.
I have not used Capybara, but I assume that it hides the caching strategy from you?
I'm currently struggling with the problem of multilingualism in an SPA.
I've come up with several solutions, like building a wrapper for the resources resx files, or saving all labels in the database, but I am wondering if any of you have found some solution which automates these steps.
Are there any practices which are specific for this problem?
For a reasonable amount of literals, I suggest to save the resources in the DB or in a .RESX file in the server. When the user logs in or you detect the language that will be used, the literals are requested by the application and saved either in a collection of your translation module or in the LocalStorage of the browser (this could be a good approach for large data).
Then this module could have some methods to retrieve the messages, probably passing a key.
Using this solution you could inject this module in the viewmodels that need to show translated literals and acces them through the view:
<p data-bind="text: resourceManager.get('M01')"></a>
For large applications that would require huge localization data to be transfered, maybe some kind of modularity could be applied and only load the resources really needed for each module/section.
I don't think making recurrent requests to the server to get the translated literals is a good practise. SPA's should provide a good user experience and loading the translated literals from the server could be a blocking issue. Text is not like an image, you can render a page without all the images loaded, imagine rendering a page without the text :o
Anyway, I think the best solution would be to keep the server as repository and create a custom JS module that takes care to get data in one or multiple loads and is able to store it somewhere in the client.
I've solved my own problem, using a custom binding and i18next.
First, I've implemented i18next for translation of my labels/buttons and other resources.
Secondly, I've added a custom Knockout bindingHandler:
ko.bindingHandlers.i18n = {
init: function (element, valueAccessor) {
var translateKey = valueAccessor();
ko.utils.setTextContent(element, $.t(translateKey));
}
};
Finally you can add the following code to your views:
<span data-bind="i18n : 'buttons.cancel'"></span>
This will automatically get the correct resource, and Knockout will handle the bindings.
Hopefully this will help others struggling with the same problem.
In this railscast our good friend Mr. Bates walks through a solution to creating an app that can search, sort, and paginate a set of data. When going through AJAX searching he provides a solution that will display results of the search the moment a user enters input into the search box. Here is his solution:
$('#products_search input').keyup(function () {
$.get($('#products_search').attr('action'), ↵
$('#products_search').serialize(), null, 'script');
return false;
});
However he states "Note that this is only a quick demo and isn’t the best way to do this. There are several jQuery plugins that you can use if you do something like this in a production app." I'm looking for an explanation on why he believes this isn't suitable for production. Thanks in advance!
There are two major issues I see with this solution. The first is that you are making an HTTP (AJAX) request every time a key is pressed, which will not be the most efficient way of doing this. The second is that you are basically calling eval in the response, and eval is bad as it can lead to malicious users executing code you don't want to be executed.
Some suggestions on improving:
Use a proper JSON parser and pass the data back as JSON. (you can use $.getJSON)
Throttle the request - don't do it on every keyUp, maybe start a timer and only submit the request if no keys have been pressed in the last second, meaning it won't make lots of calls for people who type fast.
Cache the response. If you have already searched for something, then there is no point fetching the data twice. Keep a note (in a JS Object) of previous calls in this session and their results.
I am starting to notice problems when I try and code my javascript and use functions that are in my viewmodel. Things like this:
case 37:
#if (Model.GoLeft)
{
Here I get a syntax error and the words "expected constant" for Model. Is there some solution to this? Do I need to upgrade something so it works?
I checked around on stackoverflow. Someone else suggested that I should separate my js but that doesn't help me as for example in this case where I want the keypress to do something if on a certain type of page where the Model allows it. If the js is in another file I can't code this way.
thanks
your approach is just wrong. Dont generate JS code in views by ifs. You defintely should keep your JS separetly (so that browser can efectively cache and reuse it). If you need to change behaviour of client-side code according to model values, do that by generation only some king of "flags" (JS have multiple ways to do that, i am not expert in JS - for example global variable works always, but there are more elegant and recommended ways) and in your client-side method test for their presence and fork your code by that.