accessing getRelatedDocuments from within docpad.coffee - coffeescript

Any suggestion on how to access #getRelatedDocuments() directly from within inner function. Only way I could get my snippet to work was as below where #getRelatedDocuments() is assigned to a variable outside of inner. docpad throws error stating that it is unable to access #getRelatedDocuments() function if I place it inside the inner function
getRelatedWidget: (widgetName) ->
documents = #getRelatedDocuments()
inner = ->
res = for relPost in documents
"""
<li>#{relPost.title}</li>"""
return res.join('')
outer = -> """
<aside id="related-posts">
<h3 class="widget-title">#{widgetName}</h3>
<nav class="linklist">
<ul>
#{inner()}
</ul>
</nav>
</aside>
"""
if #getRelatedDocuments().length
outer()
I'd like to rather use:
inner = ->
res = for relPost in #getRelatedDocuments()
.....
Thanks,
Colin

Make it an argument.
inner = (related_docs) ->
res = for relPost in related_docs
...
outer = -> """
<aside id="related-posts">
<h3 class="widget-title">#{widgetName}</h3>
<nav class="linklist">
<ul>
#{inner(# getRelatedDocuments())}
</ul>
</nav>
</aside>
"""

Related

Property does not exist on this collection instance while trying to iterate through foreach

I'm trying to display an edit form with current value from the database.
Here's the Controlller.
public function edit(PenerimaanHadiahSponsor $id)
{
$collection = PenerimaanHadiahSponsor::find($id);
$dataanak = Anak::find($id);
$datatp = TipeHadiahSponsor::find($id);
// dd($dataanak);
return view('sponsor.penerimaan.updatetrx', compact('collection', 'dataanak', 'datatp'));
}
For now, I try to iterate the $datanak collection, but it returns that property [id] does not exist on the collection.
Here's the blade view file
<div class="mb-3">
<label class="form-label" for="basic-form-gender">Pilih Anak</label>
<select class="form-select" id="basic-form-gender" aria-label="Default select example" name="id_anak">
<option selected="selected">Pilih Anak yg Dapat Hadiah</option>
#foreach ($dataanak as $dtanak)
<option value="{{ $dtanak -> id }}">{{ $dtanak -> fullname }}</option>
#endforeach
</select>
</div>
I expect that it could return this data because it has relation with my curent model table which named penerimaan_data_sponsors
https://cdn.discordapp.com/attachments/856336794068189208/1051057589376532580/image.png
When I try to dd($dataanak) with this method:
$dataanak = Anak::where('id', 1)->get();
It returns the collection using id = 1, but when I used the current data id which is 12, it's returns blank array. Because the current data I want to edit had id 12.
https://cdn.discordapp.com/attachments/856336794068189208/1051058294464188456/image.png
the fix was this. I removed the model 'PenerimaanHadiahSponsor' from edit function.
public function edit($id)
{
$collection = PenerimaanHadiahSponsor::find($id);
$dataanak = Anak::find($id);
$datatp = TipeHadiahSponsor::find($id);
dd($dataanak->fullname);
// return view('sponsor.penerimaan.updatetrx', compact('collection', 'dataanak', 'datatp'));
}

Angular2 Dynamic form displaying incorrect ngModel data

Im generating a table and form to edit each field but when I try to edit it, the data displayed in the input fields is incorrect.
HTML
<form (ngSubmit)="onEditSubmit()">
<span>What the form gets</span>
<div *ngFor="let k of keys; let i = index" class="form-group row">
<span>{{k|uppercase}}</span>
<div class="col-md-9">
<input [(ngModel)]="updateModels[keys[i]]" type="text" name="text-input" class="form-control" placeholder="{{k}}" />
</div>
</div>
<button>Submit</button>
</form>
JS
public data: any = [{id: 1, code1: "VALUE1", code2: "VALUE2", code3: "VALUE3"},{id: 2, code1: "TEST1", code2: "TEST2", code3: "TEST3"}];
public keys: any = ["code1","code2","code3"];
public activeRoleId = '';
public updateModels: any = {};
public toEditData: any = "";
public editedData: any = "";
constructor() {
}
onEditSubmit() {
this.editedData = this.updateModels;
}
/*CLick on element actions*/
editElement(item): void {
for (let i = 0; i < this.keys.length; i++) {
this.updateModels[this.keys[i]] = item[this.keys[i]];
}
console.log(this.updateModels);
this.toEditData = this.updateModels;
this.activeRoleId = item.id;
}
Plunker
This error is caused because of you are using a form. If you'd remove the form tags, this would work as you want. BUT, since you are using a form, each name-attribute has to be unique, so that these fields are evaluated as separate form fields.
So the solution for your problem is quite simple, just assign an unique name to your fields, you can make use of the index, so change:
name="text-input"
for example to the following:
name="text-input{{i}}"
Then it works like a charm! :) Here's the forked
Plunker

Lift (Scala) form validation

I have a question for which I couldn't find an answer anywhere in the web. I have a lift-based web application written on Scala. There is a form in my application which is driven by a snippet. I use Mapper for my models, and I use override def validations ... to define model's validation parameters. The template code looks like this:
<form class="lift:GroupManager.addGroup?form=POST&action=add">
<div class="row collapse" style="width: 30em">
<div class="small-8 columns">
<span class="group-name prefix radius"></span>
</div>
<div class="small-4 columns">
<span class="submit button small postfix radius">Add New Group</span>
</div>
</div>
</span>
</form>
The snippet code:
def addGroup = {
object groupName extends RequestVar[String]("")
def doAddGroup() = {
val group = Group.create.createdAt(new java.util.Date).groupName(groupName.is)
group.validate match {
case Nil => {
group.save
S.notice("Group '" + group.groupName.is + "' has been added successfully")
}
case errors:List[FieldError] => {
S.error(errors)
}
}
}
".group-name" #> SHtml.text(groupName.is, groupName(_), "id" -> "group-name") &
".submit" #> SHtml.submit("Add group", doAddGroup)
}
The model's validations override:
object groupName extends MappedString(this, 700) {
override def dbColumnName = "group_name"
override def dbNotNull_? = true
override def validations = valMinLen(1, S.?("Group name should not be empty!")) _ ::
valMaxLen(700, S.?("Group name should not be more than 700 characters long!")) _ ::
valUnique(S.?("Group name should be unique!")) _ ::
super.validations
}
Now everything is perfect except the fact that when invalid data is provided, S.error is used to inform user about problems. What I want to do is to highlight the form element (by applying class="error") in which the data is invalid and add a <span> element with the error message in front of the form element. Is there a simple way to do that with Lift framework? Or I should just traverse through errors:List[FieldError] and fetch field information from that array, which does not seem too elegant to me?

KnockoutJS - ViewModel Abstracion

*UPDATE* (see below)
I understand the basics of KnockoutJS. When creating a table viewmodel, one would use <tr data-bind="foreach: rows">
Now I'm trying to abstract the table viewmodel, so that I can create multiple tables with the same behaviour (sorting, editing, pagination, etc..). So what I'm aiming for is something like this:
HTML
<div class="table a" data-bind="myTableBinding: aTableViewModel"></div>
<div class="table b" data-bind="myTableBinding: anotherTableViewmodel"></div>
Main ViewModel
var MainViewModel = function () {
this.aTableViewModel = new AbstractTableViewModel({
columns: [...]
initialSort: [...]
});
this.anotherTableViewModel = new AbstractTableViewModel({
columns: [...]
initialSort: [...]
});
};
My first try was mimicking the example [simpleGrid] plugin (# http://knockoutjs.com/examples/resources/knockout.simpleGrid.1.3.js) that the KnockoutJS docs use for the [Paged grid] example.
I'm not really sure, but I think that the basic concept of abstraction isn't represented well in this plugin. When I tried to include css class into the <th> elements like so: <th class="col col-id">, <th class="col col-name">, etc, I found out this wasn't easy (impossible?) using data-bind attributes.
The data-bind attributes probably shouldn't be used for this stuff through, because these classes won't change -- they are part of a higher abstraction level: we should actually insert these classes with jQuery.tmpl or Underscore's templating system. But then I got an error saying that [This template system doesn't support use of the foreach binding] (or something like that).
My second try therefore was to implement the abstraction as it should be implemented: with the table properties (columns, etc) at another "abstraction level" than the table data:
Create the basic <tr data-bind="foreach: rows"> html at instantiation of a new specific table view model, using an "abstract" template -- this I simply did with Underscore's _.template.
Let this specific viewmodel use the above html as usual.
In CoffeeScript:
do ->
ko.dataTable =
ViewModel: (config) ->
#id = config.id
#columns = config.columns
#pageSize = config.pageSize ? 9999
#sortColumn = ko.observable (config.sortColumn ? #columns[0].col)
#sortOrder = ko.observable (config.sortOrder ? "asc")
#data = ko.observableArray (config.data ? [])
null
ko.bindingHandlers.dataTable =
init: (el, acc) ->
viewModel = acc()
$(el).find("div:first").html dataTableTemplateMaker viewModel
# ??? [A] ko.applyBindings viewModel, $(el).find("table")[0]
# ??? [B] controlsDescendantBindings: yes
null
update: (el, acc) ->
viewModel = acc()
# ??? [C]
null
And then:
<div data-bind="dataTable: groupTable">
and:
class ViewModel
constructor: ->
#groupTable = new ko.dataTable.ViewModel
id: "grouptable"
columns: [
{ col: "num", title: "Groep", editable: yes }
{ col: "subject", title: "Vak" }
{ col: "year", title: "Jaar" }
{ col: "level", title: "Niveau" }
{ col: "day", title: "Dag" }
{ col: "hour", title: "Uur" }
{ col: "place", title: "Lokaal", editable: yes }
]
pageSize: 10
sortColumn: "num"
sortOrder: "asc"
data: [] # [D]
... in which ??? marks the spot(s) where my confusion lies.
Say I do not insert lines [A] and [B]. Then of course KnockoutJS tells me that the bindings are all messed up within the html for my specific viewmodel (which is inserted into the <div>. If I do insert lines [A] and [B], then it does work for initial data (at [D]), but after that does not respond.
Alltogether: I'm quite confused about something simple as abstracting a viewmodel. Isn't there a standard solution to this in KnockoutJS? (I've googled but couldn't quite find anything...) Or am I just messing it up myself (quite possible)? ;)
*UPDATE*
I solved the problem (but maybe it's not the best / well at all -- what is your opinion?), for completeness' sake: (a condensed version -- of course you'd probably also want to observe the rows individually etc..)
HTML (yes, that is purposefully a string passed to the binding handler)
<div data-bind="myTableBinding: 'viewModelPropertyHoldingTableViewModel'"></div>
CoffeeScript
class MainViewModel
constructor: ->
#viewModelPropertyHoldingTableViewModel = new TableViewModel <options>
null
class TableViewModel
constructor: (options) ->
#columns = options.columns
#rows = ko.observableArray (options.rows ? [])
[...]
null
tableTemplateMaker = _.template '
<table>
<thead>
<tr>
[% _.map(tableViewModel.columns, function (column) { %]
<th>[%= column.title %]</th>
[% } %]
</tr>
</thead>
<tbody data-bind="foreach: rows">
<tr>
[% _.map(tableViewModel.columns, function (column) { %]
<td data-bind="text: [%= column.id %]"></td>
[% } %]
</tr>
</tbody>
</table>
'
ko.bindingHandlers.myTableBinding =
init: (element, viewModelPropertyNameAccessor, _, mainViewModel) ->
tableViewModelProperty = viewModelPropertyNameAccessor()
tableViewModel = mainViewModel[tableViewModelProperty]
$(element).html tableTemplateMaker
tableViewModelProperty: tableViewModelProperty
tableViewModel: tableViewModel
null
m = new MainViewModel
ko.applyBindings m
m.viewModelPropertyHoldingTableViewModel.data.push [...]
Why reinvent the wheel? :P
https://github.com/CogShift/Knockout.Extensions

How to create nested <ul> <li> tags with HtmlTags (FubuMVC)

I have no previous experience with FubuMVC HtmlTags library, and I simply got stuck when trying to accomplish a simple nested structure like this:
<ul>
<li>text</li>
<li>text
<ul>
<li>subtext</li>
<li>subtext</li>
</ul>
</li>
<li>text</li>
</ul>
Here's how I have it when building the string:
public static HtmlString ChildNodesRecursive(DocumentNode documentNode)
{
var tag="";
if (documentNode.Children.Count > 0)
{
tag = "<ul>";
foreach (var c in documentNode.Children)
{
tag += "<li>" + c.Name;
tag += ChildNodesRecursive(c);
tag += "</li>";
}
tag += "</ul>";
}
return new HtmlString(tag);
}
Works fine, but I like to use HtmlTags library (outside of FubuMvc, with the HtmlTags separate Nuget).
Edit : I got inspiration from both answers and came up with what I needed. So here's the code I ended up using.
public static HtmlTags.HtmlTag ChildNodesRecursiveHtmlTag(DocumentNode documentNode)
{
var ul = new HtmlTags.HtmlTag("ul");
foreach (var c in documentNode.Children)
{
var li = new HtmlTags.HtmlTag("li");
li.Add("a").Attr("href",c.ContextFullPath).Text(c.Name);
if (c.Children.Count > 0)
{
li.Children.Add(ChildNodesRecursiveHtmlTag(c));
}
ul.Children.Add(li);
}
return ul;
}
I can give you an example which may make things clearer to you:
var ul = new HtmlTag("span").AddClass("form_input");
ul.Modify(t =>
{
foreach (var value in choice)
{
t.Add("input")
.Attr("type", "radio")
.Attr("name", request.Accessor.Name)
.Attr("value", value)
.Add("span")
.AddClass("fixed-width")
.Text(value);
}
});
Gives you something like
<span class="form-input">
<input type="radio" name="bla" value="foo" />
<span class="fixed-width">foo</span>
...etc...
</span>
You can carry on nesting tags with modify and filling in the lambda. I think you will find that what you want to do is possible with the bits of syntax shown.
This code:
var root = new HtmlTags.HtmlTag("ul");
root.Add("li").Text("item1");
var child = root.Add("ul");
child.Add("li").Text("item2");
return root.ToPrettyString();
produces the following output:
<ul>
<li>item1</li><ul>
<li>item2</li>
</ul>
</ul>