How to access Another Module's Content and Presentation Items after 2sxc v10.20+ - dotnetnuke

Here is code that worked up through 2sxc 10.9.1. Though I am able to get the CmsBlock for the TabID, ModuleID and get that to .Render(), I need more. Here is the old code. Not sure it makes any difference, but this View is using the normal Link content-type and is running in an older version of the Content App (appx 3.03=ish). 2sxc has been upgraded and is now 11.22.0 LTS.
I have removed unnecessary stuff, so I doubt this runs as is...
#using ToSic.Razor.Blade
#using ToSic.SexyContent.Environment.Dnn7
#{
var Helpers = CreateInstance("_Helpers.cshtml");
// Display the items from the Manage Links module, we go in 'sideways'
// this gives us just the Content items with their Presentations settings, etc.
var sxci = Factory.SxcInstanceForModule(3360, 606); // ModuleID of Manage Links
var dyn = Factory.CodingHelpers(sxci);
var allLinks = dyn.AsDynamic(dyn.Data["Default"]);
}
#* other stuff *#
<div class="row co-documents justify-content-center align-items-center">
#foreach (var linkItem in allLinks) {
var linkInfo = Helpers.LinkInfos(linkItem.Link, linkItem.Window, linkItem.Icon);
string iconStyle = linkItem.IconStyle ?? "fas";
int linkColumns = (int)linkItem.Presentation.Columns;
string linkIconAlign = linkItem.Presentation.IconAlign;
string linkIconBGColor = linkItem.Presentation.IconBGColor;
#* other stuff *#
}
</div>
So the easy thing to figure out was how to get the module as a CmsBlock which I can Render() as is (below), but what I need to do instead is get proper access to the List of Content Items AND their Presentation data (like above, allLinks).
ToSic.Sxc.Dnn.Factory.CmsBlock(606, 3360).Render();
What am I missing? How can I get access to the other module's data like I was doing before? In this case, I do this in 3 different places on the website. So to outline this in English, I have a module that the client manages a few special links that get displayed in MegaMenus, other special nav, and directly on a couple of pages. In each place they render differently. In their "home" module, where they get edited, they just look boring like this:
I realize its something like this:
var allLinks = something1.AsList(something2.Data["Default"]);
I understand that something2 is an app instance, but how do I create it in the context of the other module?
And what is something1 nowadays? And how do instantiate it? Looks like its a new ToSic.Sxc.Code.DynamicCode() but I can't figure out how to construct that in a way that I can use or doesn't just throw errors.
Thanks in advance for any insight!!

Okay, it took a little testing, trial and error. And also I missed that DynamicCode() was a Method of the Factory class. In retrospect it does seem easy now.
So first you get the BlockBuilder
var block = Factory.CmsBlock(606, 3360);
Then you get the DynamicCode instance (Code.DnnDynamicCodeRoot) from that
var dc = Factory.DynamicCode(block);
And then things are normal
var allLinks = AsList(dc.Data["Default"]);
The rest of the code works like it did before; I can foreach through the links with Header (renamed from ListContent) and Presentation (now Content.Presentation) working just as expected.

The above answer works fine if you are inside the C# Razor template of the 2sxc View. But what if you are outside, for example in a Razor template for a DDR Menu?
Same two steps as above (get the block and the dc), but then you do NOT have access to AsList() or the App. Thankfully, you already have DynamicCode, so you could just get all the records in the Bibliography content-type like this:
<ul>
var items = dc.AsList(dc.App.Data["Bibliography"]);
foreach (var item in items)
{
<li>#item.EntityTitle</li>
}
</ul>
So once you've got your dc you've got access to all the usual 2sxc toys.

Related

how can I load a joomla module as a link?

this is my problem...
I have some of images and links that I want to load different joomla modules when user click on them.
mean each hyperlink can load another module|position
thanks all
In case that you just want to call a module's content from a url the following answer will help you.
If you just want to show / hide a module in the same page you could use something similar to my previous answer: Joomla 3 Show different modules on same position depending on toggler
Joomla provides the functionality to call a specific file of the active template by adding the tmpl=FILENAME key/value to the url's query string.
All built-in templates have a component.php file if user wants to load the template with the component only. You could check the following link for more details: Adding print pop-up functionality to a component.
You could do something similar to only show the modules that you want to load.
You could copy the component.php to a new file (I have used custom.php) and added the following php code in the <body> ... </body> part.
<?php
$jinput = JFactory::getApplication()->input;
$selectedPosition = $jinput->getString("position", "");
$selectedModule = $jinput->getString("module", "");
$selectedModuleTitle = $jinput->getString("title");
if($selectedPosition !== "") {
$modules = JModuleHelper::getModules($selectedPosition);
foreach ($modules as $module) {
echo JModuleHelper::renderModule($module);
}
} elseif ($selectedModule !== "") {
$module = JModuleHelper::getModule($selectedModule, $selectedModuleTitle);
echo JModuleHelper::renderModule($module);
}
?>
So with a similar way as loadposition / loadmodule works you could call the new template file using:
index.php?tmpl=custom&position=MODULE_POSITION
or
index.php?tmpl=custom&module=MODULE_TYPE
or
index.php?tmpl=custom&module=MODULE_TYPE&title=MODULE_TITLE
Optionally if you want to load the module with a specific style, you could pass it to the second paramter of the renderModule method like:
echo JModuleHelper::renderModule($module, array("style" => "xhtml"));
Hope this helps

How do I delete objects within objects in Angular-Meteor?

NOTE: the following code and demo are extracted from a larger Meteor + Angular project.
I have the following functions to select and delete objects:
DEMO: http://plnkr.co/edit/Qi8nIPEd2aeXOzmVR6By?p=preview
$scope.selectParty = function(party) {
$scope.party = party;
$scope.type = party.type;
$scope.date = party.date;
}
$scope.deletParty = function(party) {
$scope.parties.remove(party);
}
$scope.selectOrganizer = function(organizer) {
$scope.organizer = organizer;
$scope.name = organizer.name;
$scope.title = organizer.title;
}
$scope.deletOrganizer = function(organizer) {
$scope.party.organizers.remove(organizer);
}
The Select action works on both Parties and Organizers as you can see in the demo, displaying the data in the table underneath.
The Delete action doesn't work. Although, let me point out that in my app, the one I have on my machine and currently working on in Meteor, the Delete action works splendidly on Parties, meaning the syntax "$scope.parties.remove(party)" works. But it doesn't work on the plnkr demo for some reason :(
My question is really about the Organizers Delete action, where I'm targeting an object (organizer) inside an array inside the selected object (party)… that one doesn't work. I'm wondering why, and what is the right syntax.
NOTE 2: I'm aware of Angular's splice and index but I can't use them here as I'm not simply working with Angular arrays but with database data in Meteor.
Thanks!
The organizer is a part of the party object and not a collection on it's own. So what you would need to do is remove the party from the object and then save the party object.
Note2 is incorrect. Unless you wrote your question and plunker wrong.

meteor angular collection find method not working

I'm trying to optimize my angular/meteor code. I have a collection
Customers = new Mongo.Collection("Customers");
and the way I was displaying them was:
ng-repeat="customer in customerController.customers | filter: {customerStore: myStore} ">
and in my CustomerController
this.customers = $meteor.collection(customers);
This approach (while it works) is now starting to take up a lot of memory on the client's server as they are adding more and more stores.
So I tried to filter server side before sending information to the client.
NEW CODE:
collection code is the same
Customers = new Mongo.Collection("Customers");
ng-repeat code is different
ng-repeat="customer in customerController.getCustomers(myStore) ">
and my controller now has this method:
this.getCustomers = function(findByStore){
return Customers.find({customerStore.$ : findByStore});
}
The problem with this is that it returns a new collection each time, so angular sees it as a different object and tries to re-render the page.
https://docs.angularjs.org/error/$rootScope/infdig?p0=10&p1=%5B%5B%7B%22msg%22:%22fn:%20regularInterceptedExpression%22,%22newVal%22:21,%22oldVal%22:19%7D%5D,%5B%7B%22msg%22:%22fn:%20regularInterceptedExpression%22,%22newVal%22:23,%22oldVal%22:21%7D%5D,%5B%7B%22msg%22:%22fn:%20regularInterceptedExpression%22,%22newVal%22:25,%22oldVal%22:23%7D%5D,%5B%7B%22msg%22:%22fn:%20regularInterceptedExpression%22,%22newVal%22:27,%22oldVal%22:25%7D%5D,%5B%7B%22msg%22:%22fn:%20regularInterceptedExpression%22,%22newVal%22:29,%22oldVal%22:27%7D%5D%5D
One common mistake is binding to a function which generates a new array every time it is called.
Someone suggested i try
return $meteor.collection(Customers.find({'customerStore.$' : findByStore}));
but then I get the error
TypeError: The first argument of $meteorCollection must be a function or a have a find function property.

grails: show list of elements from database in gsp

in my grails app I need to get some data from database and show it in a gsp page.
I know that I need to get data from controller, for example
List<Event> todayEvents = Event.findAllByStartTime(today)
gets all Event with date today
Now, how can I render it in a gsp page?How can I pass that list of Event objects to gsp?
Thanks a lot
You can learn many of the basic concepts using Grails scaffolding. Create a new project with a domain and issue command generate-all com.sample.MyDomain it will generate you a controller and a view.
To answer your question create a action in a controller like this:
class EventController {
//Helpful when controller actions are exposed as REST service.
static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
def showEvents() {
List<Event> todayEvents = Event.findAllByStartTime(today)
[eventsList:todayEvents]
}
}
On your GSP you can loop through the list and print them as you wish
<g:each in="${eventsList}" var="p">
<li>${p}</li>
</g:each>
Good luck
I am not sure if this is really what you meant, because in that case I suggest you to read some more on the grails :), but anyway, for your case you can use render, redirect as well but here I am taking simplest way:
In your controller you have:
def getAllElements(){
List<Event> todayEvents = Event.findAllByStartTime(today)
[todayEvents :todayEvents ]
}
and then in the GSP(I assume you know about grails conventions, as if you don't specify view name, it will by default render gsp page with the same name as the function in the controller, inside views/):
<g:each in="${todayEvents}" var="eventInstance">
${eventInstance.<propertyName>}
</g:each>
something like this.

Show layout in Marionette.Application inside controller

I am trying to structure my code with MVC flow within my application. I am trying to show created layouts in my marionette app instance within my marionette.controller as below..
Can anyone please tell me is it a proper way to show or change layouts within controller is proper way or not? And if not then what's the proper approach for that.
My Controller
define([ 'marionette', 'app', 'index_view' ], function( Marionette, App, IndexView ) {
console.log("Inside...ViewFlow Controller.");
var ViewFlow_Controller = Marionette.Controller.extend({
loadIndex : function() {
console.log("Inside...Load Index Method.");
App.main.show( new IndexView() );
}
});
return new ViewFlow_Controller();
});
where my IndexView is like this
define(['app', 'helper', 'templates'],
function (App, Helper, templates){
console.log("Inside...Index View.");
App.Page_Index = (function(){
var Page_Index = {};
var _pageName = 'IndexPage';
var _pageLayout = Helper.newPageLayout({
name:_pageName,
panelView: Helper.newPanelView(),
headerView: Helper.newHeaderView({name:_pageName, title:'Welcome to the Index Page'}),
contentView: Helper.newContentView({name:_pageName, template: templates.content_index}),
footerView: Helper.newFooterView({name:_pageName, title:'IndexPage Footer'})
});
return Page_Index;
})();
return App.Page_Index;
});
My helper returns me App_Layout instance.
But it's not working, it's giving me an error
Uncaught TypeError:object is not a function viewflow_controller.js:12
Please help me out.
You can find the code here if you want to refer to the complete code or contribute.
Thanks in advance.
The code on GitHub seems to contain only empty files (aside from the libraries), so I'm going to assume Helper returns a layout instance (which you seem to have indicated, saying it returned an App_Layout instance).
It looks like you're using layouts wrong. The way to use layouts is basically:
Create a layout instance with regions (e.g.) panelRegion and contentRegion
Create view instances that will be displayed in the layout (e.g.) panelViewInstance and contentViewInstance
Write a handler to show your views when the layout itself is shown.
The handler should look like this:
myLayout.on("show", function(){
myLayout.panelRegion.show(panelViewInstance);
myLayout.contentRegionshow(contentViewInstance);
});
Then, show that layout in one of your app's regions:
MyApp.mainRegion.show(myLayout);
The documentation on layouts is here: https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.layout.md
You can learn more on using layouts and structuring your code in my book on Marionette.

Resources