Multi level block method is generating issue
First of all we refactored your helper for more intensive usage of content_tag
(just to get whats going in this code ^_^).
Next we add usage of output_buffer
which was defined but not used at all in helper.
After it all methods wich should be called from erb
should return nil
so they didn't appear in HTML.
And last syntactic suger was usage of instance_eval
so you don't need {|c| ...}
style blocks. You can use all variables from DataListBuilder
directly there.
module DataListHelper
def list_headers(args=[])
args = Array.new(args)
columns = []
args.map { |o| columns << content_tag(:li, o.split(":").first, :style=>"width:#{o.split(":").second}px;") }
content_tag(:ul, columns.join(" ").html_safe, :class=>"list-headers")
end
def data_list_total_records(array)
content_tag(:div, page_entries_info(array).html_safe, :class=>"total-records")
end
def data_list_for(object, headers=[], &block)
if object.is_a? Array
if object.length == 0
list_headers(headers).concat(content_tag(:strong, "<br />No records found".html_safe))
else
res_obj = data_list_total_records(object)
res_obj << content_tag(:ol, :class=>"data-list") do
res_ol = content_tag(:li) do
res = list_headers(headers)
object.each do |o|
builder = DataListBuilder.new(o)
res << content_tag(:li) do
content_tag(:ul, :id=>o.id, :class=>"list-row #{cycle('odd', 'even')}") do
capture(builder, &block)
builder.output_buffer.html_safe
end
end
end
res
end
res_ol << data_list_pagination(object)
end
res_obj
end
else
list_headers(headers).concat(content_tag(:strong, " <br />Not available."))
end
end
class DataListBuilder
include ActionView::Helpers::TagHelper
include ActionView::Helpers::CaptureHelper
include ActionView::Helpers::UrlHelper
include Rails.application.routes.url_helpers
attr_accessor :object, :output_buffer, :controller
def initialize(object)
@object, @output_buffer = object, ''
end
def column (&block)
@output_buffer << if block_given?
content_tag(:li, instance_eval(&block))
else
content_tag(:li, "")
end
nil
end
def options_column(&link_block)
@output_buffer << if block_given?
content_tag(:li) do
content_tag(:dl, :class=>'options') do
res = content_tag(:dt) do
content_tag(:a, ' '.html_safe, :href => '#')
end
res << content_tag(:dd) do
content_tag(:ul) do
instance_eval &link_block
end
end
end
end
else
content_tag(:li, "")
end
nil
end
def link_item(title, url, options={})
content_tag :li, link_to(title, url, options)
end
end
end
And your view became this:
<%= data_list_for @leads, [" :10", "Age:30", "Contact:140", "Phone:140", "Email:180", "Company:100", ""] do |l| %>
<%= l.column { link_to " ".html_safe, "leads/details/#{object.id}", :class=>:plus, :remote=>true } %>
<%= l.column { object.age } %>
<%= l.column { object.contact.complete_name } %>
<%= l.column { object.contact.phones.blank? ? "-" : object.contact.phones.first.phone_number } %>
<%= l.column { object.contact.emails.blank? ? "-" : object.contact.emails.first.email } %>
<%= l.column { object.company.title } %>
<%= l.options_column do %>
<%= link_item 'Show', lead_path(object.id) %>
<%= link_item 'Edit', edit_lead_path(object.id) %>
<%= link_item 'New Note', "leads/#{object.id}/notes/new", :class=>"display-newxdoc", :id=>object.id %>
<%= link_item 'Create Opportunity', new_lead_opportunity_path(object.id) %>
<% end %>
<% end %>
Jinja2 Multi-level template inheritance issue
I understand your issue: you've got template A, template B (extends template A), and template C (extends template B). There's a block defined in template A, but it's not showing up in the page that uses template C, unless you define that block in template B. If you do that, then the block in question shows up.
First: you are correct in your understanding that this is not how the Jinja template hierarchy is supposed to work. Second, I did not encounter your issue (found a different one, though), and I have constructed a proof to demonstrate this. Here's what I did (again, using Python 3 and Django 1.11):
$ python startproject myapp
In the myapp/myapp/settings.py
file, I updated the template engine:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'DIRS': [
os.path.join(BASE_DIR, 'myapp/templates') # hack / should add `myapp` to INSTALLED_APPS instead
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
In myapp/myapp/urls.py
, I created a dummy view function & route:
from django.conf.urls import url
from django.shortcuts import render_to_response
def home(request):
return render_to_response('dashboard.html')
urlpatterns = [
url(r'^$', home),
]
And finally, I established those templates, but I removed the call to import your macros, along with all instances of static()
.
Here is the myapp/myapp/templates/skeleton.html
file:
<!doctype html>
<html lang="en">
<head>
{% block head_content %}
<meta charset="utf-8">
<title> {% if page_title %} {{ page_title }} | {% endif %} Bhargavi Books & Stationery </title>
{% endblock head_content %}
</head>
<body>
<div id="navigation">
{% block navigation %}
<div class="ui three item menu">
<a class="active item">Home</a>
<a class="item">New Bill</a>
<a class="item">View Bills</a>
</div>
{% endblock navigation %}
</div>
<div id="frame">
{% block frame_content %}
<p> Body content goes here. Body for {{ content_name }}</p>
{% endblock frame_content %}
</div>
<div id="app">
{% block app_content %}
<p> APP content goes here. Body for {{ content_name }}</p>
{% endblock app_content %}
</div>
{% block scripts %}
{% endblock scripts %}
</body>
</html>
Here is the myapp/myapp/base.html
file:
{% extends "skeleton.html" %}
{% block frame_content %}
Frame Content
{% endblock frame_content %}
{% block scripts %}
{{ super() }}
{% endblock scripts %}
And here is the myapp/myapp/templates/dashboard.html
file:
{% extends "base.html" %}
<div>
{% block body_content %}
Body 3
{% endblock body_content %}
</div>
<div>
{% block app_content %}
DASHBOARD
{% endblock app_content %}
</div>
And here is the output, after viewing that page in my browser:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title> Bhargavi Books & Stationery </title>
</head>
<body>
<div id="navigation">
<div class="ui three item menu">
<a class="active item">Home</a>
<a class="item">New Bill</a>
<a class="item">View Bills</a>
</div>
</div>
<div id="frame">
Frame Content
</div>
<div id="app">
DASHBOARD
</div>
</body>
</html>
Since this all works as expected*, my conclusion is that you might have a problem with the base.html
template file. Perhaps it's failing to import your macros, and subsequently not behaving correctly? I notice a trailing comma in there, and I'm not sure if that could be problematic or not. I would suggest using the above code as a starting point, and then slowly add back in the parts that I stripped out, and perhaps the problem will become visible/understandable.
*One thing I found odd, that I don't understand: the body_content
block is completely missing from my output, unless I define that block in the skeleton.html
template. It doesn't work if I define it in the base.html
template, which seems wrong to me, because then we're not really extending that second template (base.html
)... so there does seem to be something weird there... but I was not able to encounter the original issue you described, so maybe this will be helpful in that particular regards, at least.
Multi-level drop down menu in CSS not working properly
To fix the position of the submenu, and prevent the size of the item at the main menu to change, you can do as follows:
give the submenu (ul element- can be what you declared as .menu ul li ul
):
position:absolute
padding:0
(the built-in padding of the ul element is what you called "margin of unknown origin")left:100%
to set the submenu location.top:0
to set the submenu location.
give it's parent (li element- can be what you declared as .menu li
)):
position:relative
As for the last issue, personally I think using "nth-child" for your case is not a good choise- I whould prefer using a dedicated class for active item.
But if you want to solve what you did here, just be more specific about what item you want to style:
instead of this selector: .menu ul li:nth-child(2)
,
use this selector: .menu > ul > li:nth-child(2)
.
so the style will be applied to the second direct li
child of the main menu only.
Facing Css issue in multi Level Menu
The CSS should be targeting only the child element whose parent has .active class,
.active > app-submenu > ul {
display: block !important;
}
We need to modify the app.component and submenu.component (both HTML and TS)
Now to make this work on clicking the parent elements, we need a variable which will tell us which li is selected, we can use data attribute of the element to save its state, instead of creating a new variable.
<li [attr.data-selected]="false"> /* content */ </li>
and to access it we give an angular ID to the element and pass it as arguement in the NgClass
<li #thisLiElement [attr.data-selected]="false" [ngClass]="setActiveClass(thisLiElement)"> /* content */ </li>
Now the data attribute needs to be updated when clicked upon.
<li *ngFor="let menu of navItems" (click)="clickedEvent($event); $event.stopPropagation();" #thisLiElement [attr.data-selected]="false" [ngClass]="setActiveClass(thisLiElement)">
The defination for clickedEvent and setActiveClass are as follows, which toggles on current elements dataset
clickedEvent(event){
if (event.currentTarget["dataset"].selected === "false")
event.currentTarget["dataset"].selected = "true";
else
event.currentTarget["dataset"].selected = "false";
}
setActiveClass(thisLiElement) {
return thisLiElement.dataset.selected === "true" ? { "active": true } : { "active": false };
}
Note: The mat-icon if conditions should be also updated for above change as follows
<mat-icon *ngIf="menu.children && menu.children.length > 0">{{iconState(thisLiElement)}}</mat-icon>
and the defination for iconState should be,
iconState(thisLiElement) {
return thisLiElement.dataset.selected === "true" ? "expand_less" : "expand_more";
}
Also there is no need for @output in submenu component, so i have removed the emitter and the function subMenuClicked
Updated StackBlitz over here.
Hope it helps.
Testing for Adjacent Cells In a Multi-level Grid
- I actually have 5 levels not 2, so I could potentially get a list like "A8A1A, A8A1B, B1A2A, B1A2B".
- Adding a new cell to compare still requires me to compare all the other cells before it (seems like the best I could do for this step is
O(n))- The cells aren't all 3x3 blocks, they're just that way for my example. They could be MxN blocks with different M and N for different
levels.
I don't see a problem with these points: if a cell is not adjacent at the highest level one then we can stop the computation right there and we don't have to compute adjacency at the lower levels. If there are only five levels then you'll do at most five adjacency computations which should be fine.
- In my current implementation above, I have separate functions to check adjacency if the cells are in the same blocks, if they are in separate horizontally adjacent blocks or if they are in separate vertically adjacent blocks. That means I have to know the position of the two blocks at the current level before I call one of those functions for the layer below.
You should try to rewrite this. There should only be two methods: one that computes whether two cells are adjacent and one that computes whether two cells are adjacent at a given level:
RelativePosition isAdjacent(String cell1, String cell2);
RelativePosition isAdjacentAtLevel(String cell1, String cell2, int level);
The method isAdjacent
calls the method isAdjacentAtLevel
for each of the levels. I'm not sure whether cell1
or cell2
always contain information of all the levels but isAdjacent
could analyze the given cell strings and call the appropriate level adjacency checks accordingly. When two cells are not adjacent at a particular level then all deeper levels don't need to be checked.
The method isAdjacentAtLevel
should do: lookup M and N for the given level, extract the information from cell1
and cell2
of the given level and perform the adjacency computation. The computation should be the same for each level as each level, on its own, has the same block structure.
Setup of multi-level and dependent observables
You can achieve the desired result the mergeMap
operator.
import { mergeMap, map } from 'rxjs/operators';
createAndGetAntity(result) {
return this.service.createAndGetEntity(result.data.order).pipe(
mergeMap((response: EntityResponse<OrderModel>) => {
if (result.data.unknownLocation) {
if (result.data.isRedundant) {
return this.secondService.createWithRedundancy(someData);
} else {
return this.secondService.createEntity(someData);
}
}
return of(true);
}),
map(() => true),
);
}
I would handle dispatching the success and error actions in the subscribe block, and not in the service method itself.
this.service.dispatchErrorAction(result).subscribe(
(order) => this.dispatchSuccessAction(order),
(err) => this.dispatchErrorAction(err)
)
Related Topics
Pg_Config, Ruby Pg, Postgresql 9.0 Problem After Upgrade, Centos 5
Database Cleaner Not Working in Minitest Rails
Find Number of Bytes a Particular Hash Is Using in Ruby
Getaddrinfo Error with Mechanize
How to Get the Number of Elements Having Same Attribute in HTML in Watir
Rails How to Change Attribute Name When Rendering JSON
Ruby: Differencebetween the Comparatives: "||" and "Or"
How to Implement Yes/No Instead of Boolean for Certain Cases in Rails
Change String in a Date Format to Another Format
Sort a List of Objects by Using Their Attributes in Ruby
Custom Filtering of Parameters in Rails 3 Using Config.Filter_Parameters
Could Not Find Rake-10.1.0 in Any of the Sources