Composable Ractive js component - javascript

I'm working on a Ractive js component that represents a table. It works ok but recently I added some functionality: filters, status bar, left column checkboxes, table header. This table component is used throughout the application everywhere.
The problem is that in different places I need only some combination of these functions. In the current implementation I have a lot of ifs in the template and I want to get rid of them.
At the moment I want to use the decorator pattern but have no idea how to implement this especially with the fact that I need to mess with the core table template.
Table template:
{{#if status_bar}}
<table class="list-status">
<tbody>
<tr>
<td><input type="checkbox" checked="{{.select_all}}"></td>
<td>
{{#if has_filters}}
<span>Показать:</span>
{{#each filters:i}}
<button on-tap="#this.fire('activateFilter', event, i)" {{#if active}}class="active"{{/if}}>{{title}}</button>
{{/each}}
{{/if}}
{{#if ready}}
<span class="badge lists-badge">{{ collection.total_count }}</span>
{{#if selected.length > 0}}
<span class="badge lists-badge" style="background-color: red;">{{ selected.length }}</span>
{{/if}}
{{/if}}
</td>
</tr>
</tbody>
</table>
{{/if}}
<table class="{{class}}">
{{#if header}}
<thead>
<tr>
{{^hideSelectColumn}}
<th></th>
{{/hideSelectColumn}}
{{#each titles}}
<th class={{class}}>{{title}}</th>
{{/each}}
</tr>
</thead>
{{/if}}
<tbody>
{{#if ready}}
{{#each diff_create:i}}
<tr class="just-created">
{{^hideSelectColumn}}
<td class="{{firstColumnClass}}">
<div style="position: relative;"></div>
</td>
{{/hideSelectColumn}}
{{>pending}}
</tr>
{{/each}}
{{#if diff_create.length > 0}}
<tr>
<td colspan={{column_count}}></td>
</tr>
{{/if}}
{{#each page_models}}
<tr {{#if mfd}} class='mfd' {{/if}}>
{{^hideSelectColumn}}
<td class="{{firstColumnClass}}">
<input type="checkbox" class="list-checkbox" name='{{selected}}' value='{{#index}}'/>
<div style="position: relative;"></div>
</td>
{{/hideSelectColumn}}
{{>content}}
</tr>
{{/each}}
{{^page_models}}
<tr>
<td style='text-align:center; font-weight: bold; font-size: 15px' colspan={{column_count}}>Пусто!</td>
</tr>
{{/}}
{{/if}}
{{^ready}}
<tr>
<td style='text-align:center; font-weight: bold; font-size: 15px' colspan={{column_count}}>Загрузка...</td>
</tr>
{{/ready}}
</tbody>
</table>
<div class="pages">
{{#if pages_more_than_one}}
<ul class="pagination">
{{#if has_prev_page}}
<li class="arrow-left"><a on-tap='prevPage'><span class="icon-arrow-left4"></span></a></li>
{{/if}}
{{#each pages}}
<li class='{{#index+1==current_page ? "active": ""}}'><a on-tap='#this.fire("goToPage", #index+1)'>{{#index+1}}</a></li>
{{/each}}
{{#if has_next_page}}
<li class="arrow-right"><a on-tap='nextPage'><span class="icon-arrow-right8"></span></a></li>
{{/if}}
</ul>
{{/if}}
<div class="pages-count">
<select class="form-control" value="{{collection.perpage}}">
<option value='2'>2</option>
<option value='5'>5</option>
<option value='10'>10</option>
<option value='15'>15</option>
<option value='20'>20</option>
<option value='25'>25</option>
</select>
</div>
</div>
Thanks in advance.

Ractive has named yields where you can define placeholders in your layout and let the consuming component define what goes in there. Think of it like a layouting mechanism.
A simple example is a modal, where you have a header, body and footer which may be different for each instance. A modal component could be defined only as the layout of the modal (think empty bootstrap modal) and a bunch of yields resembling insertable positions.
const Modal = Ractive.extend({
template: `
<div class="modal">
<div class="modal__header">{{yield header }}</div>
<div class="modal__body">{{yield body }}</div>
<div class="modal__footer">{{yield footer }}</div>
</div>
`
})
On the consuming component, you use the layout component and define what goes in those positions. Note that the yield contents can be anything, even other components.
const Page = Ractive.extend({
components: { Modal },
template: `
<div class="page">
<div class="page__stuff">
...
</div>
<Modal>
{{#partial header }}
This is the header
{{/partial}}
{{#partial body }}
This is the body
{{/partial}}
{{#partial footer }}
This is the footer
{{/partial}}
</Modal>
</div>
`
});
In your case, you can break up your table into components (i.e. filters, status bar, left column checkboxes, table header) and define a layout component. Then, whenever you need it, you use the layout component, stick into it whatever you want wherever you want.
A more advanced feature is Anchors. Together with ractive.attachChild() and ractive.link(), you can attach components to anchors manually, on-the-fly. It's essentially how Ractive mounts components and binds data when it sees a component on the template. Except this time, the functionality is exposed on the API.

Related

Angular Pagination : Display a set of A4 sized pages

I am working on pagination using NgbdPaginationBasic
app.module.ts
import { NgbdPaginationBasic } from './pagination-basic';
I need to create a set of pages in A4 size with Header and Footer visible only in the first two pages. I have applied pagination on the body only
app.html
<table class="table">
<tr>
<th>id</th>
<th>name</th>
<th>email</th>
</tr>
<tr *ngFor="let item of data | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize">
<td>{{item.id}}</td>
<td>{{item.first_name}}{{item.last_name}}</td>
<td>{{item.email}}</td>
</tr>
</table>
Here is a StackBlitz I created for demonstration. The pagination is working fine on the body but the Header and Footer I want them to be hidden after the 2nd page.
Is there a way to do it or any other tool or thing I can use? All three parts of the page(header,body,footer) should have the same pagination tag.
Just use *ngIf, for ex.:
<div style="border:1px solid black;margin-bottom:4px" *ngIf="page <= 2"> <---
<hr/><span> HEADER </span><hr/>...
Your code:
<div>
<div style="border:1px solid black;margin-bottom:4px" *ngIf="page <= 2">
<hr/><span> HEADER </span><hr/>
<div class="intro mt-3 ml-3">
<span>John Doe</span>
<br/>
<span>99/123.342 LAT Street</span>
<br/>
<span>Mars Community</span>
<br/>
<span>XYZ Country</span>
<br/>
<span>Ph. 123243423423</span>
<br/>
<br/>
<span class="mt-2">Dear John</span>
<br/>
</div>
</div>
<div style="border: 1px solid red">
<hr/><span style="color : navy">MAIN BODY</span><hr/>
<table class="table">
<tr>
<th>id</th>
<th>name</th>
<th>email</th>
</tr>
<tr *ngFor="let item of data | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize">
<td>{{item.id}}</td>
<td>{{item.first_name}}{{item.last_name}}</td>
<td>{{item.email}}</td>
</tr>
</table>
</div>
<div style="border :1px solid black;margin-top:3px" *ngIf="page <= 2">
<hr/><span> Footer </span><hr/>
<p><strong>PLEASE READ THIS</strong><p>
<span>THIS IS THE FOOTER. HEADER AND FOOTER TO BE DISPLAYED FOR PAGES 1 and 2 ONLY </span>
</div>
<div>
<ngb-pagination [pageSize]="25" [collectionSize]="100" [(page)]="page" aria-label="Default pagination"></ngb-pagination>
<hr>
Hope it helps!

The css attribute that limits the number of characters I don't know why

overflow:hidden;white-space:nowrap;text-overflow:elipsis;
The Divtag is broken because it doesn't have a lot of properties. I don't know the solution. I want to hear your opinion.
<div class="col boardsBox" style="margin-right:0.5%">
<h5 style="padding-top:2%">#lang('home/main.community')
<i class="fa fa-angle-right"></i>
</h5>
<hr>
<table>
<tbody>
#foreach($communities as $community)
<tr>
<td style="padding-top:0.5%; overflow:hidden;white-space:nowrap;text-overflow:ellipsis;">
<a class="boardsFont" href="{{ route('community.show',['boardNum'=>$community->num])}}">
<i class="fa fa-check-square"></i> {{ $community->title}}
#if($community->comment_count != 0)
<span style="color:gray">({{ $community->comment_count }})</span>
#endif
</a>
</td>
</tr>
#endforeach
</tbody>
</table>
</div>
To get the ellipsis and overflow - you need to set a width or max-width on the element that contains the text (in this case its the td).
Note that I didn't have access to your actual content - so just used the table structure and created dummy text within the a elements to demonstrate the short text displays fine, but when the text is longer than the spedicifed max-width - the truncation occurs and the ellipsis is shown at the end of the text.
td {
padding-top:0.5%;
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;
max-width: 300px
}
<table>
<tbody>
<tr>
<td >
<a class="boardsFont" href="#"> This is a short message </a>
</td>
</tr>
<tr>
<td >
<a class="boardsFont" href="#"> This is a really long and extended message to demonstrate the ellipsis content</a>
</td>
</tr>
</tbody>
</table>

EmberJS Rendering Delay

I have a print button that am using an {{#if}} conditional to show when a box gets expanded. I want the box to be expanded and then show the print icon at the foot of the box. But for some reason it is getting rendered early and shown in line with the collapsed box then put in the right place once the box is fully expanded. Here is my code:
Print Icon Template:
{{#if view.showPrintButton}}
<div class="print pull-right">
Print Discussion<i class="fa fa-print"></i>
</div>
{{/if}}
Box template:
{{#if permissions.comment}}
<div {{bindAttr class="controller.audienceIsShared:shared view.commentEditorExpanded:expanded :createComment"}}>
<div class="author-image-container content">
<img src="{{unbound Informal.Registry.user.pictureUrl}}" class="author-image pull-left" />
</div>
{{#if view.commentEditorExpanded}}
<div class="comment-editor-container content">
<div class="boxSizingDefault text">
{{
view view.commentEditorClass
disabledBinding="view.commentFormDisabled"
viewName="commentEditor"
valueBinding="controller.commentInProgress.initialBody"
attachmentsBinding="controller.commentInProgress.attachments"
}}
</div>
{{#if controller.audienceIsShared}}
<div class="contextualMessage">This comment will be seen across business units</div>
{{/if}}
</div>
{{#if notificationRecipients.length}}
<div class="notificationRecipients small detail">
<span>These subscribers will be notified of your comment:</span>
{{#if notificationRecipientsIsExpandable}}
{{#if view.notificationRecipientsExpanded}}
{{#with sortedNotificationRecipients}}{{> initials}}{{/with}}
{{else}}
{{#with collapsedNotificationRecipients}}{{> initials}}{{/with}}
<span class="link" {{action "expandNotificationRecipients" target="view"}}>
, {{collapsedNotificationRecipientsRemainingCount}} more...
</span>
{{/if}}
{{else}}
{{#with sortedNotificationRecipients}}{{> initials}}{{/with}}
{{/if}}
</div>
{{/if}}
View:
showPrintButton: function () {
return (this.get("expanded") !== false) && !this.get("editorExpanded");
} .property("expanded", "editorExpanded")
Thanks!

Ng-show not working as expected? Angular

As is my understanding of Angular, only one of the two following elements should be visible at a time, but for some reason, both are displaying. Is there a mistake in my code I just can't see?
Am I using ng-show incorrectly?
<div class="no_people" ng-show="!person.name">
<p>no people</p>
</div>
<div ng-repeat="person in details.people">
<div class="persons_table">
<table>
<tbody>
<tr class="top_row">
<td colspan="2">
<span class="person_name">
{{ person.name }}
</span>
<span class="person_address" >
{{ person.address }}
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
I think this way it should work:
<div class="no_people" ng-hide="details.people.length">
<p>no people</p>
</div>
The person variable is only accessible inside the ng-repeat.
And using ng-hide instead of ng-show=! is maybe a bit more cleaner.
As I can see, you need this:
<div class="no_people" ng-hide="details.people.length > 0">
<p>no people</p>
</div>

Ember breaking after specifying route

I'm following the ember tutorial at http://emberjs.com/guides/. My issue happens when they add the following to app.js.
App.PostsRoute = Ember.Route.extend({
model: function() {
return myPosts;
}
});
Before I add this, the ember inspector does not have any problems. After I add this, the ember inspector tells me "Ember application not detected."
The code in my index looks like this. It is taken directly from the video.
<script type="text/x-handlebars" id="posts">
<div class="container-fluid">
<div class="row-fluid">
<div class="span3">
<table class='table'>
<thead>
<tr><th>Recent Posts</th></tr>
</thead>
{{#each model}}
<tr><td>
{{#link-to 'posts' this}}{{title}} <small class='muted'>by {{author.name}}</small>{{/link-to}}
</td></tr>
{{/each}}
</table>
</div>
<div class="span9">
{{outlet}}
</div>
</div>
</div>
</script>
Thanks

Categories

Resources