Question
I'm developing a fairly large app and I've run into a problem that seems common. But I haven't been able to find any solutions to it on the spine groups or here at SO.
So the question is, how do I make sure, that parent stacks becomes active when nested stacks responds to a route. How is this solved properly?
I managed to solve this by simply using #active within the parent controller for the route. This is doing the same as this.active. Here is an example of how i've done it…
Spine = require('spine')
$ = Spine.$
# Controllers
Main = require('controllers/posts/posts.main')
Nav = require('controllers/navigation/navigation')
class Posts extends Spine.Controller
className: 'posts top-controller'
constructor: ->
super
#nav = new Nav
#main = new Main
#routes
'/posts/new': ->
#active()
#nav.post.active()
#main.new.active()
'/posts/suggestion': ->
#active()
#nav.normal.active(title: "Groups near by")
#main.matches.active()
'/posts/:id': (params) ->
#active()
#nav.chat.active()
#main.show.active(params)
#append #nav, #main
module.exports = Posts
Related
I have entity ListSettings which is used as Content-Item type for 2 layouts. Each layout is used 3 times on different pages.
The code I'm writing is not executed on the page - it's outside of 2sxc module.
So I wan't to find out on which page each object of entity ListSettings is. TabId is the best. Filtering by layout could be helpful as well since I need 3 tabIds that use 1 of the 2 layouts.
How do I do that programmatically? There's a lot of data inside of each entity including some relationships, children, parents and so on. Also I'm sure that all this data could be taken from the database manually, but it seems to be a hard way for me.
Bottom line: I have 6 entities. I want to get their tabIds and layouts programmatically. Layouts are optional but would be good.
Any suggestions?
This is quite challenging, because there are so many steps involved. But you can find something that does something similar here https://2sxc.org/dnn-tutorials/en/razor/2sa110/page
Here is an excerpt of the code:
// CONSTANTS
// this key is used in module settings
const string SettingsCG = "ToSIC_SexyContent_ContentGroupGuid";
// create array with all 2sxc modules in this portal
List<ModuleInfo> GetAllModulesOfPortal(int portalId) {
var mc = ModuleController.Instance;
var dnnMod2sxcContent = mc.GetModulesByDefinition(portalId, "2Sexy Content");
var dnnMod2sxcApp = mc.GetModulesByDefinition(portalId, "2Sexy Content App");
var mergedMods = new ModuleInfo[dnnMod2sxcContent.Count + dnnMod2sxcApp.Count];
dnnMod2sxcContent.CopyTo(mergedMods);
dnnMod2sxcApp.CopyTo(mergedMods, dnnMod2sxcContent.Count);
var allMods = mergedMods
.Where(m => m.DefaultLanguageModule == null)
.Where(m => !m.IsDeleted)
.Where(m => m.ModuleSettings.ContainsKey(SettingsCG));
return allMods.ToList();
}
What is the recommended way to have mdl components affect the layout of the page in a single-page application using elm and elm-mdl?
Can we pass the layout messages, like Model.Layout.ToggleDrawer directly to model.mdl (in the standard setup), and if yes, how?
Or should we maintain a separated record element in the model, like model.layout : Material.Layout.Model, to which we forward these messages? But in this case, how to initialize the view?
Context
I am using elm-mdl version 8.1.0, with elm version 0.18. I am trying to layout the basic architecture for a single-page application with elm, and this library. I have taken inspiration from here and there, as well as this ticket, but I have not seen what I was looking for, or understood it if it was there.
Examples of what I tried
For re-usability, the main model of my application is the only one containing a Material.Model entry:
type alias Model =
{ drawer : MyDrawer
, ...
, mdl : Material.Model
}
From the component MyDrawer, I want to define a button that will send a ToggleSignal. I have a case in my main update method that forwards this signal to the Model.Layout.update method, using the Model.Layout.ToggleSignal. However, the return type of this call is a Material.Layout.Model, which I don't have in my own Model.
If I define add a layout : Material.Layout.Model to my own model, I can forward the calls to this element, but how do I initialize the view? My view so far is this:
view : Model -> Html Msg
view model =
Layout.render Mdl
model
[ Layout.fixedHeader
, ...
According to the signature of Layout.render, since my model contains a layout field, this should be taken into account. The relevant part of my update method is
ToggleDrawer ->
let
( updatedLayout, cmd ) = Material.Layout.update Material.Layout.ToggleDrawer model.layout
( updatedDrawer, _ ) = Drawer.update subMsg model.drawer
in
( { model | drawer = updatedDrawer, layout = updatedLayout }, Cmd.map MdlLayout cmd )
And yet, when clicking on the button, the drawer does not hide.
Thank you in advance for any help about this - the library and the language are such a joy to use already!
The Material.Layout.render function retrieves its model from model.mdl.layout, not from model.layout.
A good way to toggle the drawer is to use toggleDrawer to issue a suitable command in your update function, like so:
ToggleDrawer ->
let
( updatedDrawer, _ ) = Drawer.update subMsg model.drawer
in
( { model | drawer = updatedDrawer, layout = updatedLayout }
, Layout.toggleDrawer Mdl
)
I've got a problem and hope you can help me.
I have multiple QQmlWidgets where different instances of same components should be shown.
The components are created at runtime and use specific properties from it's parent widget.
The problem is, that there are multiple nested items in those components, so they are loading very slow.
I've decided to load them all to QQmlEngine at application preload stage, and after just create them when necessary.
So all my QQmlWidgets got same QQmlEngine and same root context.
To differ properties of different widgets I'm creating every instance of component in separate context (one per QQmlWidget).
After creating I'm setting parent item of newly created object to root item of QQmlWidget;
The problem is that the root item is referenced in the dynamically created objects and they could not find it.
Can you suggest any solution? I'm posting simplified version of my code below.
// main.cpp
QQmlEngine* e = new QQmlEngine;
QWidget* ww1 = new QWidget;
QWidget* ww2 = new QWidget;
QQuickWidget* w1 = new QQuickWidget(e, ww1);
QQuickWidget* w2 = new QQuickWidget(e, ww2);
w1->setSource(QUrl::fromLocalFile("main.qml"));
w2->setSource(QUrl::fromLocalFile("main.qml"));
QQmlComponent* comp = new QQmlComponent(e, "comp.qml");
QQmlContext* c1 = new QQmlContext(e);
QQmlContext* c2 = new QQmlContext(e);
QQuickItem* it1 = qobject_cast<QQuickItem*>(comp->create(c1));
it1->setParentItem(w1->rootObject());
QQuickItem* it2 = qobject_cast<QQuickItem*>(comp->create(c2));
it2->setParentItem(w2->rootObject());
ww1->show();
ww2->show();
//main.qml
Rectangle {
id: root
}
//comp.qml
Rectangle {
anchors.top : root.top
}
the error:
comp.qml - ReferenceError: root is not defined
Thanks in advance.
When a component is being loaded a parent is not set and it becomes set only after call of setParentItem method. It can be fixed by setting anchor when parent changes.
// comp.qml
Rectangle {
onParentChanged: { anchors.top = parent.top; }
}
I am trying to spec the click event handler on the following Backbone view:
class ItemView extends Backbone.View
events:
"click": "addToCurrentlyFocusedList"
addToCurrentlyFocusedList: (e) =>
window.currentlyFocusedList.add #model
This is what I have:
describe "ItemView", ->
beforeEach ->
#item = new Backbone.Model
id: 1
name: "Item 1"
#view = new ItemView model: #item
describe "when clicked", ->
it "adds the item to the currently focused list", ->
window.currentlyFocusedList = sinon.stub()
window.currentlyFocusedList.add = sinon.stub()
#view.$el.trigger "click"
expect(window.currentlyFocusedList.add).toHaveBeenCalledWith #item
This works but it bothers me for some reason. Maybe it feels too much like I am testing implementation.
One possible improvement I can see is moving the click event handler, the spec, and the currentlyFocusedList into a new view called AppView:
describe "AppView", ->
beforeEach ->
#view = new AppView
it "adds a clicked item to the currently focused list", ->
$clickedItem = #view.$(".item:first")
$clickedItem.trigger "click"
expect(#view.currentlyFocusedList.pluck('id')).toInclude $clickedItem.attr('data-id')
It's nice that this also removes window pollution. It also tests that the item really is added to the collection. That aside, is moving the event handler and spec into AppView better than my first approach? Is there a better way to go about this?
I would stub out window.currentlyFocusedList with a dummy Collection, and test that it was added there. Something along these lines:
beforeEach ->
#collection = new Backbone.Collection()
spyOn(window, 'currentlyFocusedList').andReturn #collection
it "adds the item to the collection", ->
#view.$el.click()
expect(#collection).toInclude #item
This tests what your code actually does; the code for how adding an item to a collection affects the view lives somewhere else, and should be tested somewhere else.
I have a simple menu hierachy in a Joomla 1.5 site:
[Newsletters] -> [publisher A] -> [Newsletter A1]
-> [Newsletter A2]
-> [publisher B] -> [Newsletter B1]
-> [Newsletter B2]
When navigating this hierarchy using the menu items or breadcrumbs, the SEF URL's are as expected;
/newsletters/pubA.html
/newsletters/pubA/letterA1.html
/newsletters/pubA/letterA2.html
/newsletters/pubB.html
/newsletters/pubB/letterAB.html
/newsletters/pubB/letterAB.html
However, when navigating the hierarchy using links inside the pages, the url's get messed up. Read on for more details :)
The pages are generated by a component. I've implemented a JRouter to generate SEF URL's. With SEF turned on, I can correctly navigate the hierachy using menu items and the standard breadcrumbs.
However, I also want to navigate by links on the pages themselves (for example, by linking to all of a publisher's newsletters on the publisher's page, or by linking back to the publisher's page from a newsletter's page). This works fine when going from publisher to newsletter. The component calls
JRoute::_('index.php?option=' . $option . '&view=newsletter&newsletterid=' . $newsletterId );
and (correctly) generates a URL like:
/newsletters/pubA/letterA1.html
However, when a user is on a newsletter page and wants to go back up to the publisher's page, things go wrong. For some reason the publisher's alias gets added after the newsletter's alias in the URL, as if it was below the newsletter in the hierachy. The component calls
JRoute::_('index.php?option=' . $option . '&view=publisher&publisherid=' . $publisherId );
but that (incorrectly) generates a URL like:
/newsletters/pubA/letterA1/pubA.html
If I navigate forward to a newsletter again from the above URL, then the URL becomes
/newsletters/pubA/letterA1/letterA1.html
/newsletters/pubA/letterA1/pubA.html
/newsletters/pubA/letterA1/letterA1.html
/newsletters/pubA/letterA1/pubA.html
(i.e., it doesn't go deeper than one or two segment(s) 'wrong'.)
Also, please note that navigation does work (meaning, the right page is opened) -- it's just the URL that looks weird.
I don't see how I could generate the expected URL's as shown at the top; there doesn't seem to be a way to specify 'relative to what' the 'first' segment should be. Should I be tapping into JSite::getRouter() somehow?
The router code is pretty straight forward. It's the first time I write a router, so I could have messed up something. I do find it suspicious that ParseRoute is only ever called with a single segment.
function ComponentBuildRoute(&$query)
{
$segments = array();
if (isset($query['view']))
{
if (isset($query['newsletterid']))
{
$alias = { figure out newsletter alias from newsletter id }
$segments[] = $alias;
unset($query['newsletterid']);
}
else if (isset($query['publisherid']))
{
$alias = { figure out publisher alias from publisher id }
$segments[] = $alias;
unset($query['publisherid']);
}
unset($query['view']);
}
return $segments;
}
function ComponentParseRoute($segments)
{
$vars = array();
$id = { try to retrieve newsletter id matching alias in $segments[0] }
if (!empty($id))
{
$vars['view'] = 'newsletter';
$vars['newsletterid'] = $id;
return $vars;
}
$id = { try to retrieve publisher id matching alias in $segments[0] }
if (!empty($id))
{
$vars['view'] = 'publisher';
$vars['publisherid'] = $id;
return $vars;
}
return $vars;
}
I don't want to use an absolute URL because the publisher's menu item sits under the newsletters menu... obviously there must be a way of doing this as both the menu items and the breadcrumb modules figured it out...
Thanks
There is a problem with your ComponentBuildRoute. In the else if block where you deal with publisherid you unset newsletterid. I am not sure if that is the problem, but fixing it would be the first step to get this issue resolved.