How to pass content while calling app.router.navigate() in Framework7? - frameworks

Here is the dynamic page route:
{
path: '/news/',
name:'news',
content: '<div class="page newPage"><div class="page-content"><div class="block"><p> This page created dynamically</p></div></div></div>',
}
I am calling the dynamic page like this:
app.router.navigate({name:'news'});
My question is how to change the content of that page by passing some parameters, something like this:
app.router.navigate({name:'news', new-content:'<div>Hi new content</div>'});

try to append your content or any variable to ( params ) before you navigate
app.router.params["PageMode"] = "new";
app.views.main.router.navigate({name:'newbill'});
then you can receive it when page init
$(document).on('page:init', '.page[data-name="newbill"]', function (page) {
console.log(app.router.params.PageMode);
});

The content to a page are passed in through the routes for example :
routes = [
{
path: '/news/:id/:content',
url: 'somepage.html'
}
]
so when you sending the parameters to the route you will simply do like :
var id = parseInt(someNewsID);
var content = 'Lorem ipsum ...........';
app.mainView.router.navigate('/news/' + id + '/' + content);
making sure you are separating your variables with a slash as in the path
Retrieving the values will be as simple as :
var myID = app.mainView.router.currentRoute.params.id;
var myContent = app.mainView.router.currentRoute.params.content;
and then you can manipulate your dom using JavaScript or JQuery to load the values and use them

Related

Wagtail - how to get tags to work with `telepath` (tags in streamfield)?

I can use tags in regular page fields without any issue. When using tags within blocks (within a streamfield), the UI works and the tags are saved BUT the current page tags do not show up when loading the page in the admin. That's because the current value is not in the template anymore, it's in a JSON loaded via telepath.
I can confirm that the tags are saved and present in the data passed to initBlockWidget in the page source but these are ignored. Also, if I used a regular text field instead of the tag-widget, I can see the saved-values in the admin.
This is the code I have (which used to be enough before the refactor with telepath).
from wagtail.admin.widgets import AdminTagWidget
class TagBlock(TextBlock):
#cached_property
def field(self):
field_kwargs = {"widget": AdminTagWidget()}
field_kwargs.update(self.field_options)
return forms.CharField(**field_kwargs)
I think the following link is what I need to complete somehow to get it to work: https://docs.wagtail.io/en/stable/reference/streamfield/widget_api.html#form-widget-client-side-api
I've tried with this:
class AdminTagWidgetAdapter(WidgetAdapter):
class Media:
js = [
"wagtailadmin/js/vendor/tag-it.js",
"js/admin/admin-tag-widget-adapter.js",
]
register(AdminTagWidgetAdapter(), AdminTagWidget)
And under js/admin/admin-tag-widget-adapter.js:
console.log("adapter"); // this shows up in the console
class BoundWidget { // copied from wagtail source code
constructor(element, name, idForLabel, initialState) {
var selector = ':input[name="' + name + '"]';
this.input = element.find(selector).addBack(selector); // find, including element itself
this.idForLabel = idForLabel;
this.setState(initialState);
}
getValue() {
return this.input.val();
}
getState() {
return this.input.val();
}
setState(state) {
this.input.val(state);
}
getTextLabel(opts) {
const val = this.getValue();
if (typeof val !== 'string') return null;
const maxLength = opts && opts.maxLength;
if (maxLength && val.length > maxLength) {
return val.substring(0, maxLength - 1) + '…';
}
return val;
}
focus() {
this.input.focus();
}
}
// my code here:
class AdminTagWidget {
constructor(html, idPattern) {
this.html = html;
this.idPattern = idPattern;
}
boundWidgetClass = BoundWidget;
render(placeholder, name, id, initialState) {
console.log("RENDER", placeholder, name, id, initialState); // this does not show
var html = this.html.replace(/__NAME__/g, name).replace(/__ID__/g, id);
var idForLabel = this.idPattern.replace(/__ID__/g, id);
var dom = $(html);
$(placeholder).replaceWith(dom);
// eslint-disable-next-line new-cap
return new this.boundWidgetClass(dom, name, idForLabel, initialState);
}
}
console.log("here") // does show in the console
// variants I've tried:
//window.telepath.register('wagtail.admin.widgets.tags.AdminTagWidget', AdminTagWidget);
//window.telepath.register('wagtail.widgets.AdminTagWidget', AdminTagWidget);
window.telepath.register('path.where.its.used.AdminTagWidget', AdminTagWidget)
The log from my custom render method does not show. It seems that I'm not calling the right path within window.telepath.register but I don't know how what the string is supposed to be...
I'm not even sure if this is the right way forward.
Notes:
it works in regular field, the question is about tags in blocks
I'm using Wagtail version 2.13.2 but I've also tried with 2.15 without any difference.
In the console, I can log window.telepath and see my custom widget. It's just not "applied" to anything
Your WidgetAdapter class needs a js_constructor attribute:
class AdminTagWidgetAdapter(WidgetAdapter):
js_constructor = 'myapp.widgets.AdminTagWidget'
class Media:
js = [
"wagtailadmin/js/vendor/tag-it.js",
"js/admin/admin-tag-widget-adapter.js",
]
Any string value will work here - it just needs to uniquely identify the class, so it's recommended to use a dotted module-like path to avoid colliding with others. This then matches the string you pass to window.telepath.register on the Javascript side:
window.telepath.register('myapp.widgets.AdminTagWidget', AdminTagWidget)

How to create a local empty JSON Model from OData metadata

Is there a way to create a local empty JSON file (with all entities and properties filled in) from the metadata of the oData service? I need this for the create scenario, where I can bind the properties to the view controls. I tried the following code, but did not work. Will appreciate your suggestions.
this.getOwnerComponent().getModel().getMetaModel().getODataEntitySet("EntitySetName");
Error:
Uncaught TypeError: Cannot read property 'getObject' of null
at constructor.h.getODataEntityContainer (ODataMetaModel-dbg.js:692)
at constructor.h.getODataEntitySet (ODataMetaModel-dbg.js:731)
at eval (eval at _prepareCreatePage (ObjectPage.controller.js:74), <anonymous>:1:48)
at f._prepareCreatePage (ObjectPage.controller.js:74)
at f._onObjectPatternMatched (ObjectPage.controller.js:40)
at constructor.b.fireEvent (EventProvider-dbg.js:228)
at constructor.<anonymous>
SAP does very similar stuff in their sample pages: https://sapui5.hana.ondemand.com/#/entity/sap.ui.table.Table/sample/sap.ui.table.sample.OData2/code
Your first part is more or less correct, this is a function to store the meta model in a seperate JSONModel:
function () {
const that = this;
const oModel = this.getOwnerComponent().getModel();
const oMetaModel = oModel.getMetaModel();
oMetaModel.loaded().then(function () {
that.setModel(oMetaModel, "meta");
});
}
The interesting part is how to access stuff:
const sBasePath = "/dataServices/schema/[${namespace}===\'NAME_OF_YOUR_ODATA_SRV\']/entityType/[${name}===\'NameOfYourEntity\']"
const oEntityInformation = oMetaModel.getProperty(sBasePath);
const aKeys = oMetaModel.getProperty(sBasePath + "/key/propertyRef");
const aAllProperties = oMetaModel.getProperty(sBasePath + "/property");
const oSingleProperty = oMetaModel.getProperty(sBasePath + "/property/[${name}===\'NameOfYourProperty\']");
You can even access the model in your XML view:
columns="{
path: 'meta>/dataServices/schema/[${namespace}===\'NAME_OF_YOUR_ODATA_SRV\']/entityType/[${name}===\'NameOfYourEntity\']/property',
factory: '.columnFactory'
}"
Note that NameOfYourEntity has to be the name of the single Entity, so there is no Set at the end.
Not sure, what you want exactly but this script will write the metadata in JSON format in a blob. The save dialog in browser appears after that.
var oDataModel = this.getOwnerComponent().getModel();
oDataModel.attachMetadataLoaded(null, function() {
var oMetaData = oDataModel.getServiceMetadata(); //Read the metadata
var blob = new Blob([JSON.stringify(oMetaData)], {
type: "text/plain;charset=utf-8"
}); //Create a blob with metadata string in JSON format
if (navigator.msSaveBlob) {
return navigator.msSaveBlob(blob, "metadata.json"); //For IE
} else {
//For Chrome and FF we create a Link with a download attribute and trigger the click on it
var sUrl = URL.createObjectURL(blob); //Create the URL for the blob object
var oLink = document.createElement("a"); //Create link element
oLink.download = "metadata.json" //Set download attribute for link
oLink.href = sUrl; //Set href attribute for link
document.body.appendChild(oLink); //Append link to body
oLink.click(); //Click on link
oLink.remove(); //Remove link
}
});

Zend_Navigation add dynamically parameter after question mark

I'm using Zend_Navigation' reading fron xml.
I want to add to the menu created from it an additional parameter (got it from the request for the first page).
e.g
if the first page is mysite.com/pages/page1?Id=42
then
clicking on the menu would add the "?Id=42" to each link.
Easiest way to do this is by extending the Zend_Controller_Action_Helper_Url class, and adding the query string to the parent::url() result. Than, you need to inject your url helper into the mvc page, by calling Zend_Navigation_Page_Mvc::setUrlHelper($yourUrlHelper).
Example of a query string supported url helper:
class My_Helper_Url extends Zend_Controller_Action_Helper_Url
{
public function url($urlOptions = array(), $name = null, $reset = false, $encode = true)
{
$queryString = $this->getRequest()->getServer('QUERY_STRING');
return parent::url($urlOptions, $name, $reset, $encode) .
($queryString ? '?' . $queryString : '');
}
}

Fill in some from HTML form slots using link from another page?

I have a fairly vanilla HTML page with an (inquiry) form. That form has topic field. I'd like to be able to link to that page from another topic-specific page (using an A tag?) on the website, causing that topic field (and maybe some subset of other fields) to be filled in automatically.
Suggestions?
Add a custom param (topic name) to the page where the link points and use it as a subject/topic field.
like:
link
Then, on a target page (with inquiry) use this javascript:
<script type="text/javascript">
// Read a page's GET URL variables and return them as an associative array.
function getUrlVars()
{
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for(var i = 0; i < hashes.length; i++)
{
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
}
var params = getUrlVars();
document.getElementById('your_topic_field_id').value = params['topic_title'];
</script>

Url.Action handling null values or using javascript clientside values

OK my original post:
Url.Action is throwing error CS1026: ) expected
got answered. However I discovered that one of the objects in the Model that I was relying on for an ID is null. I can't figure out how to rewrite this to make it work.
var url = '<%= Url.Action(
"List",
"PlacementAgreementAgencyPlacementAgreementsPlacement",
new {
Domain = "Placement",
Id = Model.Item.PlacementAgreement.PlacementAgreementId,
agencyPlacementAgreementId = Model.Item.AgencyPlacementAgreementId,
Page = Model.PageNo
}) %>';
I need something like this (which is currently saying too many characters in character literal which I think might be related to single/double quotes.
var url = '<%= Url.Action(
"List",
"PlacementAgreementAgencyPlacementAgreementsPlacement",
new {
Domain = "Placement",
Id = ' + $("#PlacementAgreementId").val() +',
agencyPlacementAgreementId = ViewData.Model.AgencyPlacementAgreement == null ? 0 : ViewData.Model.AgencyPlacementAgreement.AgencyPlacementAgreementId,
Page = ViewData.Model.PageNo
}
) %>';
Have also tried:
var url = '<%= Url.Action(
"List",
"PlacementAgreementAgencyPlacementAgreementsPlacement",
new {
Domain = "Placement",
Id = %>' + $("#PlacementAgreementId").val() +'<%=,
agencyPlacementAgreementId = ViewData.Model.AgencyPlacementAgreement == null ? 0 : ViewData.Model.AgencyPlacementAgreement.AgencyPlacementAgreementId,
Page = ViewData.Model.PageNo}) %>';
But this mix of javascript and url.action is just confusing me. My issue is that there is no property on my ViewData class that contains the id.. but if I view source on the page I can see that it is being stored client side.
Any ideas? Thanks!
Ended up going back to what was originally there and passing what looks like old school querystring parameters.
var url = '<%= Url.Action("List") %>?page=' + pageNo +
'&agencyplacementagreementid=' + $("#AgencyPlacementAgreementId").val();
So not sure if I was on the completely wrong track before and you're supposed to do it this way - or if there was a way of doing it like my original approach. But it's now working! :)
Jen,
You are mixing client side Javascript with C# server side, not a good mix!
The only way I see you doing this is by putting a placeholder and then do a replace in Javascript, something like:
var url = '<%= Url.Action(
"List",
"PlacementAgreementAgencyPlacementAgreementsPlacement",
new {
Domain = "Placement",
Id = 9999,
agencyPlacementAgreementId = ViewData.Model.AgencyPlacementAgreement == null ? 0 : ViewData.Model.AgencyPlacementAgreement.AgencyPlacementAgreementId,
Page = ViewData.Model.PageNo}) %>';
And then do a replace in Javascript:
var realUrl = url.replace('9999', $("#PlacementAgreementId").val());