Spinejs routing not saving state - coffeescript

I'm trying to get states into my spine application. On click, an item is added to a list. An url is then created and navigated to, and then the list get's rendered. However, when I use the browsers "back" functionality, the list doesn't change back to the previous state. How to get this to work?
This is the relevant code, I left out what seemed irrelevant, but if more is required I'll provided it.
class App extends Spine.Controller
constructor: ->
super
#products = new Products
#filters = new Filters
Filter.bind 'filterAdded', => #navigateAfterFilterChange()
Filter.bind 'filterRemoved', => #navigateAfterFilterChange()
Spine.Route.setup( history: false )
renderAll: ->
#products.render()
#filters.render()
navigateAfterFilterChange: ->
Spine.Route.navigate( encodeURIComponent( JSON.stringify( _.map( Filter.active_filters, ( filter ) -> { t: filters.type, v: filters.value } ) ) ) )
class Filter extends Spine.Model
listen: => #This is used to make the right list item listen to a click event
$("'a[data-cid=\"#{ #id }\"]'").one 'click', #triggerFilter
triggerFilter: (e) =>
e.preventDefault()
filter = Filter.find( $( e.currentTarget ).attr( 'data-cid' ) )
if #active
#active = false
Filter.active_filters = _.reject Filter.active_filters, (x) -> ( x.type is filter.type and x.value is filter.value )
#save()
Filter.trigger 'filterRemoved', #
else
#active = true
Filter.active_filters.push filter
#save()
Filter.trigger 'filterAdded', #
class Filters extends Spine.Controller
constructor: ->
super
#utils = new GeneralScripts
#createFilters()
#listenForTypeActivation()
#routes
"": ( params ) ->
#render()
"*glob": ( params ) ->
#render()

Not sure, but looks like you may need to send params with render()
class Filters extends Spine.Controller
constructor: ->
super
#utils = new GeneralScripts
#createFilters()
#listenForTypeActivation()
#routes
"": ( params ) ->
#render(params)
"*glob": ( params ) ->
#render(params)
you would also need to handle params in the render method of course

Related

elm-graphq: Get list of all objects from connection query

I am in deep water.
I am trying to get all rows from a PostgreSQL database through a GraphQL api.
I am using the dillonkearns/elm-graphql elm package.
This is my query (image for context):
query getAllTheDATA {
allEvents1S {
nodes {
name
stopTime
stopDate
startTime
startDate
responsible
}
}
}
Current code:
This code is just to make the query with the selectors.
module Test exposing (..)
import Json.Decode as JD exposing (Decoder)
import Graphql.Operation exposing (RootQuery)
import Graphql.SelectionSet as SelectionSet exposing (SelectionSet,with)
import Calendar.Object exposing (Events1(..))
import Calendar.Object.Events1 as Events1
import Calendar.Object.Events1SConnection as EConn
import Calendar.Query as Query
import Calendar.Scalar exposing (Id(..))
import Calendar.Interface
import Calendar.Interface
type alias Activity2 =
{ name : Maybe String -- The name of each activity
, start_date : Maybe String -- The start date for an activity
, start_time: Maybe String -- The start time for an activity
, stop_date : Maybe String -- The end date for an activity
, stop_time: Maybe String -- The end time for an activity
, responsible : Maybe String -- who is responsible
}
eventsListSelection : SelectionSet (List Activity2) Calendar.Object.Events1SConnection
eventsListSelection =
EConn.nodes <----- this is where the problem lies
fetchEventsQuery : SelectionSet (Maybe (List Activity2)) RootQuery
fetchEventsQuery =
Query.allEvents1S (List Activity2) eventsListSelection
Questions:
How would I, in elm using the elm-graphql package, collect this data and store it in a list?
import Browser
import Calendar.Object.Events1 as Events1Object
import Calendar.Object.Events1SConnection as Events1SConnection
import Calendar.Query as Query
import Graphql.Operation exposing (RootQuery)
import Graphql.SelectionSet as SelectionSet exposing (SelectionSet)
import Html exposing (Html, div, text)
-- MAIN
main : Program () Model Msg
main =
Browser.element
{ init = init
, update = update
, view = view
, subscriptions = subscriptions
}
-- MODEL
type alias Model =
{ events : Status (List Event) }
type Status a
= Failure
| Loading
| Success a
type alias Event =
{ name : String
, startDate : String
, startTime: String
, stopDate : String
, stopTime: String
, responsible : String
}
-- INIT
init : () -> ( Model, Cmd Msg )
init _ =
( Model Loading
, Graphql.Http.send GotEvents (Graphql.Http.queryRequest "https://graphql-calendar.example.com/" query)
)
-- UPDATE
type Msg
= GotEvents (Result (Error (List Event)) List Event)
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
GotEvents result ->
case result of
Err _ ->
( { model | events = Failure }
, Cmd.none
)
Ok events ->
( { model | events = Success events }
, Cmd.none
)
-- VIEW
view : Model -> Html Msg
view model =
case model.events of
Success events ->
div []
[ List.map viewEvent events ]
Loading ->
div []
[ text "Loading" ]
Failure ->
div []
[ text "Failure" ]
viewEvent : Event -> Html Msg
viewEvent event =
div []
[ text event.name ]
-- GRAPHQL
query : SelectionSet (List Event) RootQuery
query =
Query.allEvents1s
(Events1SConnection.nodes
(SelectionSet.map6 Event
Events1Object.name
Events1Object.startDate
Events1Object.startTime
Events1Object.stopDate
Events1Object.stopTime
Events1Object.responsible
)
)
|> SelectionSet.nonNullOrFail
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none

How to use play's form validation to check if the password matches

My form looks like:
case class PasswordData(currentPassword: String, newPassword: String, verifyPassword: String)
val passwordForm = Form(
mapping(
)(PasswordData.apply)(PasswordData.unapply) verifying("Passwords do not match", fields => fields match {
case data => (data.newPassword == data.verifyPassword)
})
)
My controller action follows the usual pattern:
passwordForm.bindFromRequest.fold(
error => {},
form => {}
)
The problem I have now is I need to verify if the entered 'currentPassword' is the same as what is on the user's object.
userDao.getById(userId).password == form.currentPassword
But I can't do this because I am not sure how to pass int he userId to my form definition since it is dynamic.
i.e. I can't do it like:
"currentPassword" -> nonEmptyText.verifying(....) // userId not in scope
Update
I am trying to display these errors also using (they don't currently display the error, I only see the ul tags).
#if(form.hasGlobalErrors) {
<ul>
#form.errors.foreach { error =>
<li>#error.message</li>
}
</ul>
}
Nothing is stopping you from making your passwordForm a def, where you can pass in a user model.
def passwordForm(user: User) = Form(
mapping(
"currentPassword" -> nonEmptyText.verifying("Incorrect password.", enteredPassword =>
// some comparison with `enteredPassword` and the user
),
...
)(PasswordData.apply)(PasswordData.unapply)
.verifying("Passwords do not match", data =>
data.newPassword == data.verifyPassword
)
)
passwordForm(user).bindFromRequest.fold(
error => ...,
form => ...
)
Also, to print out the global errors in the view, they are accessed via globalErrors, and not the normal errors field. You should also use map instead of foreach. foreach returns Unit, which will not print anything to the view.
#if(form.hasGlobalErrors) {
<ul>
#form.globalErrors.map { error =>
<li>#error.message</li>
}
</ul>
}

How to write left outer join using MethodCallExpressions?

The code block below answers the question: "How do you perform a left outer join using linq extension methods?"
var qry = Foo.GroupJoin(
Bar,
foo => foo.Foo_Id,
bar => bar.Foo_Id,
(x,y) => new { Foo = x, Bars = y })
.SelectMany(
x => x.Bars.DefaultIfEmpty(),
(x,y) => new { Foo = x, Bar = y});
How do you write this GroupJoin and SelectMany as MethodCallExpressions? All of the examples that I've found are written using DynamicExpressions translating strings into lambdas (another example). I like to avoid taking a dependency on that library if possible.
Can the query above be written with Expressions and associated methods?
I know how to construct basic lambda expressions like foo => foo.Foo_Id using ParameterExpressions MemberExpressions and Expression.Lambda() , but how do you construct (x,y) => new { Foo = x, Bars = y })??? to be able to construct the necessary parameters to create both calls?
MethodCallExpression groupJoinCall =
Expression.Call(
typeof(Queryable),
"GroupJoin",
new Type[] {
typeof(Customers),
typeof(Purchases),
outerSelectorLambda.Body.Type,
resultsSelectorLambda.Body.Type
},
c.Expression,
p.Expression,
Expression.Quote(outerSelectorLambda),
Expression.Quote(innerSelectorLambda),
Expression.Quote(resultsSelectorLambda)
);
MethodCallExpression selectManyCall =
Expression.Call(typeof(Queryable),
"SelectMany", new Type[] {
groupJoinCall.ElementType,
resultType,
resultsSelectorLambda.Body.Type
}, groupJoinCall.Expression, Expression.Quote(lambda),
Expression.Quote(resultsSelectorLambda)));
Ultimately, I need to create a repeatable process that will left join n Bars to Foo. Because we have a vertical data structure, a left-joined query is required to return what is represented as Bars, to allow the user to sort Foo. The requirement is to allow the user to sort by 10 Bars, but I don't expect them to ever use more than three. I tried writing a process that chained the code in the first block above up to 10 times, but once I got passed 5 Visual Studio 2012 start to slow and around 7 it locked up.
Therefore, I'm now trying to write a method that returns the selectManyCall and calls itself recursively as many times as is requested by the user.
Based upon the query below that works in LinqPad, the process that needs to be repeated only requires manually handling the transparent identifiers in Expression objects. The query sorts returns Foos sorted by Bars (3 Bars in this case).
A side note. This process is significantly easier doing the join in the OrderBy delegate, however, the query it produces includes the T-SQL "OUTER APPLY", which isn't supported by Oracle which is required.
I'm grateful for any ideas on how to write the projection to anonymous type or any other out-of-the-box idea that may work. Thank you.
var q = Foos
.GroupJoin (
Bars,
g => g.FooID,
sv => sv.FooID,
(g, v) =>
new
{
g = g,
v = v
}
)
.SelectMany (
s => s.v.DefaultIfEmpty (),
(s, v) =>
new
{
s = s,
v = v
}
)
.GroupJoin (
Bars,
g => g.s.g.FooID,
sv => sv.FooID,
(g, v) =>
new
{
g = g,
v = v
}
)
.SelectMany (
s => s.v.DefaultIfEmpty (),
(s, v) =>
new
{
s = s,
v = v
}
)
.GroupJoin (
Bars,
g => g.s.g.s.g.FooID,
sv => sv.FooID,
(g, v) =>
new
{
g = g,
v = v
}
)
.SelectMany (
s => s.v.DefaultIfEmpty (),
(s, v) =>
new
{
s = s,
v = v
}
)
.OrderBy (a => a.s.g.s.g.v.Text)
.ThenBy (a => a.s.g.v.Text)
.ThenByDescending (a => a.v.Date)
.Select (a => a.s.g.s.g.s.g);
If you're having trouble figuring out how to generate the expressions, you could always get an assist from the compiler. What you could do is declare an lambda expression with the types you are going to query with and write the lambda. The compiler will generate the expression for you and you can examine it to see what expressions make up the expression tree.
e.g., your expression is equivalent to this using the query syntax (or you could use the method call syntax if you prefer)
Expression<Func<IQueryable<Foo>, IQueryable<Bar>, IQueryable>> expr =
(Foo, Bar) =>
from foo in Foo
join bar in Bar on foo.Foo_Id equals bar.Foo_Id into bars
from bar in bars.DefaultIfEmpty()
select new
{
Foo = foo,
Bar = bar,
};
To answer your question, you can't really generate an expression that creates an anonymous object, the actual type isn't known at compile time. You can cheat kinda by creating a dummy object and use GetType() to get its type which you could then use to create the appropriate new expression, but that's more of a dirty hack and I wouldn't recommend doing this. Doing so, you won't be able to generate strongly typed expressions since you don't know the type of the anonymous type.
e.g.,
var dummyType = new
{
foo = default(Foo),
bars = default(IQueryable<Bar>),
}.GetType();
var fooExpr = Expression.Parameter(typeof(Foo), "foo");
var barsExpr = Expression.Parameter(typeof(IQueryable<Bar>), "bars");
var fooProp = dummyType.GetProperty("foo");
var barsProp = dummyType.GetProperty("bars");
var ctor = dummyType.GetConstructor(new Type[]
{
fooProp.PropertyType,
barsProp.PropertyType,
});
var newExpr = Expression.New(
ctor,
new Expression[] { fooExpr, barsExpr },
new MemberInfo[] { fooProp, barsProp }
);
// the expression type is unknown, just some lambda
var lambda = Expression.Lambda(newExpr, fooExpr, barsExpr);
Whenever you need to generate an expression that involves an anonymous object, the right thing to do would be to create an known type and use that in place of the anonymous type. It will have limited use yes but it's a much cleaner way to handle such a situation. Then at least you'll be able to get the type at compile time.
// use this type instead of the anonymous one
public class Dummy
{
public Foo foo { get; set; }
public IQueryable<Bar> bars { get; set; }
}
var dummyType = typeof(Dummy);
var fooExpr = Expression.Parameter(typeof(Foo), "foo");
var barsExpr = Expression.Parameter(typeof(IQueryable<Bar>), "bars");
var fooProp = dummyType.GetProperty("foo");
var barsProp = dummyType.GetProperty("bars");
var ctor = dummyType.GetConstructor(Type.EmptyTypes);
var newExpr = Expression.MemberInit(
Expression.New(ctor),
Expression.Bind(fooProp, fooExpr),
Expression.Bind(barsProp, barsExpr)
);
// lambda's type is known at compile time now
var lambda = Expression.Lambda<Func<Foo, IQueryable<Bar>, Dummy>>(
newExpr,
fooExpr,
barsExpr);
Or, instead of creating and using a dummy type, you might be able to use tuples in your expressions instead.
static Expression<Func<T1, T2, Tuple<T1, T2>>> GetExpression<T1, T2>()
{
var type1 = typeof(T1);
var type2 = typeof(T2);
var tupleType = typeof(Tuple<T1, T2>);
var arg1Expr = Expression.Parameter(type1, "arg1");
var arg2Expr = Expression.Parameter(type2, "arg2");
var arg1Prop = tupleType.GetProperty("Item1");
var arg2Prop = tupleType.GetProperty("Item2");
var ctor = tupleType.GetConstructor(new Type[]
{
arg1Prop.PropertyType,
arg2Prop.PropertyType,
});
var newExpr = Expression.New(
ctor,
new Expression[] { arg1Expr, arg2Expr },
new MemberInfo[] { arg1Prop, arg2Prop }
);
// lambda's type is known at compile time now
var lambda = Expression.Lambda<Func<T1, T2, Tuple<T1, T2>>>(
newExpr,
arg1Expr,
arg2Expr);
return lambda;
}
Then to use it:
var expr = GetExpression<Foo, IQueryable<Bar>>();

How to create read-only field in View

I have a form with 2 fields - empno and name. Both fill up with default value. When display in view, I want empno is read-only and name is editable.
In view creation, I am using #leaveform.value.get.empno to display ready-only and work fine. The problem only occur during insert with error ([NoSuchElementException: None.get]).
Questions:
The problem is return error does not have value property. What else could I use to get the value?
Could I skip #inputText for read-only field?
Refer below my code:
// ***** CONTROLLER *****//
val leaveform = Form[LeaveModel](
mapping(
"empno" -> nonEmptyText,
"name" -> nonEmptyText
)((no, empno) => LeaveModel(empno, name))
((leave: LeaveModel) => Some(leave.empno, leave.name))
)
def create = withAuth { username => implicit request =>
// Define default values
val empno = "STUDENT"
val name = ""
// Set default values
val filledForm = leaveform.fill(LeaveModel(empno,name))
Ok(html.leave.form(filledForm))
}
def insert = Action (
implicit request => {
leaveform.bindFromRequest.fold(
error => {
BadRequest(html.leave.form(error)) // Question 1. Here is the error.
},
leave => {
LeaveModel.insert(leave)
Redirect(routes.indexController.index())
}
)
}
)
// ***** VIEW START***** //
#(leaveform: Form[LeaveModel])
#leaveform.value.get.empno
#helper.form(
action = (routes.LeaveController.update(oid)),
'id -> "leaveform") {
#inputText(leaveform("empno")) // Question 2.
#inputText(leaveform("name"))
}
It is not mandatory to use the form helpers. If you use them you can pass the attribute readonly or style the field with CSS to make it look read only.
Twitter bootstrap disabled by CSS:
#inputText(
editForm("createdOn"),
'id -> "createdOn",
'class -> "input-xlarge disabled",
'_label -> Messages("createdOn"),
'_help -> ""
)
Pass optional attribute: readonly
#inputText(
editForm("createdOn"),
'id -> "createdOn",
'class -> "input-xlarge",
'_label -> Messages("createdOn"),
'readonly -> "readonly",
'_help -> " This is read only"
)
You can also don't resend the field, but display its value:
<span class="date">Created on: #editForm("createdOn").value</span>
Update 2018-01-24
Play field is now returning a Optional, see the docs. This means you can get the value from the field like:
#form("fieldName").getValue.get (can throw a NPE)
#form("fieldName").getValue.getOrElse("defaultValue")
Try using the Flash context when returning a form to the user:
def create = withAuth { username => implicit request =>
// leaveForm initialization as before
// use form data from flash if present
val form = if (flash.get("error").isDefined)
leaveForm.bind(flash.data)
else
leaveForm
Ok(stakeholders.register(form))
}
def insert = Action { implicit request =>
leaveForm.bindFromRequest.fold(
hasErrors = { form =>
Redirect(routes.Leaves.create). // put correct route here
flashing(Flash(form.data) +
("error" -> Messages("validation.errors"))) // customize error message
},
leave => {
LeaveModel.insert(leave)
Redirect(routes.indexController.index())
}
)
}
HTH, Erich

Coffeescript classes, method and instance variables

I'm going to implement some kind of a Pagniator class in Coffeescript. The Paginator class should hold the information about currentPage, maxPages, columnNames, ...
So my first approach is this:
class Paginator
currentPage = -1
rowCount = -1
pageSize= -1
columnNames = null
constructor: (#config) ->
setup: ->
#config.ajax(
cache: false
type: "GET"
contentType: "application/json"
dataType: "json"
success: (data) =>
this.configurationReceived(data)
)
configurationReceived: (data) =>
this.storeConfig(data)
this.setupGUI()
this.loadPage(1)
$('.pagination ul li').click( ->
Paginator.loadPage($(this).text())
return false
)
storeConfig: (jsonData) =>
rowCount = jsonData['rowAmount']
pageSize = jsonData['pageSize']
columns = jsonData['columns']
return
The #config is a jsRoutes.controllers.xxx from Play 2.0 Framework jsroutes object.
On Page load I do
paginator = new Paginator jsRoutes.controllers.PlayerController.paginatorConfiguration()
paginator.setup()
But I get a "this.storeConfig is not a function" all the time. Can someone help me on that? Do I misuse the class syntax here? My aim is to have the state of the Paginator encapsulated in a Paginator object (instance). On startup I want to do some initialization stuff that is done via a AJAX call to a "route" which is a HTTP endpoint.
Thanks
There seems to be a problem with the indentation here:
$('.pagination ul li').click( ->
Paginator.loadPage($(this).text())
return false
) # <---
should be
$('.pagination ul li').click( ->
Paginator.loadPage($(this).text())
return false
)
Because of this, the following code containing the definition of the method "storeConfig" is not part of the class, therefore "this.storeConfig" is not a function.
You can easily see this if you copy-past your code into the "Try-coffescript" form at coffeescript.org and examine the JavaScript output.