I have a folderish dexterity content type and I have an event subscriber. When the content type is created, I create a Collection, which shows the children in the container according to several parameters. After the collection is created, I try to set the default page of the container to the collection.
def myContainerAdded(my_container, event):
#get container
#set advanced query for collection
#create collection with api.create
my_container.setDefaultPage(new_collection.id)
The subscriber in configure.zcml
<subscriber
for="my.product.my_container.IMyContainer
zope.lifecycleevent.interfaces.IObjectAddedEvent"
handler=".events.myContainerAdded" />
Unfortunately, the default page is not being fully set. It just shows the container page, but the Collection is selected under the 'Display' drop down.
If I click "Change content item as default view" and select the collection, it does change the default page to the collection.
Earlier, I was using a "setuphandler" to setup a folder structure (as opposed to an add event), and setDefaultPage was working. Am I forgetting a step since I'm attempting this through an event?
I am using plone.4.3.
Edit: I also tried:
my_container.default_page = new_collection.id
Edit:
I found something interesting. I temporarily commented out the code related to the collection in the event subscriber. I manually added the collection to the container object and then set the default page of the container to the collection. The container's default page was the collection.
Maybe something isn't getting indexed right?
In fact everything went well, it's just that after creating a Dexterity-based content-type, one will land on the default-view's URL, meaning '/view' is appended to the item's URL, which is an alias to the default-view-method and here resolves to the 'folder_listing'-template.
To overcome this quickly, you can add a redirect to the object's URL in the subscriber's method, without any view-name appended to the URL:
event.REQUEST.RESPONSE.redirect(my_container.absolute_url())
Related
I was asked to capture the analytics on a website. The website is made up of 5 web pages, but I now realize that the domain is the same and the only thing that changes is the URL fragment, i.e. www.domain.com#a, www.domain.com#b. The only info that comes through to GA is the domain and it does not include the URL fragments. The tracking code I'm using is Tealium and the data is being sent back to Google Analytics. How can I set this up so that i can see the entire URL in GA including the URL fragments?
So, from Tealium's perspective we need to trigger a view event when a new fragment is loaded (if I am understanding this correctly).
If we assume that the fragment change occurs on a link click then we need to trigger the view event when the link click occurs.
From the GA perspective, we need to trigger a view that captures the new information. For a view this is likely to be location, path and title.
Therefore, we need Tealium to construct the new data points and then pass them in a view event to GA.
The simplest way to do this in Tealium (all things being equal) is via a jQuery onHandler Extension
The jQuery extension requires the following information:
jQuery selector (or selectors) to pay attention to
"Trigger On" event type (this will be Click in this example)
Tracking event type to run (View event in this case)
Variable & values to set
Tealium jQuery onHandler extension config
note it's always a good idea to set a condition on your jQuery extensions so that they only run when needed instead of all the time and everywhere
In this extension, I have set the following:
jQuery Selector: '#MyID_1, #MyID_2, #MyID_3' -- yes you can pass a list of selectors or nearly any other valid jQuery selector statement
Trigger On: 'click'
Tracking Event: 'view'
3 Variables:
a. 'page_name' : $(this).text(); //get the link text
b. 'my_url' : utag.data['dom.url']+$(this).attr('href') //building the full URL including the fragment
//utag.data['dom.url'] is a variable/datapoint that Tealium automatically generates
c. my_path : utag.data['dom.pathname']+$(this).attr('href'); //building the path
//utag.data['dom.pathname'] is a variable/datapoint that Tealium automatically generates
NOTE: make sure to set the type for each these to "JS Code" otherwise your JavaScript will be quoted out as a string.
Why these three variables? As I understand GA, these are the values it would expect for a new page view -- location/URL, path, and Title so we are constructing those values in the extension to pass them to GA on the view event.
Now, we just need to map these new variables to GA.
my_path gets mapped to page in the GA mapping toolbox
page_name gets mapped to title
location isn't a default option in the mapping toolbox so we need to add a custom destination variable called location and map my_url to it.
custom variable mapping for GA
That's how you do it from within Tealium and minimal coding. If for some reason you don't want to / can't do it inside of Tealium, this provides us with a very nice template for a custom function to add to our codebase:
`$(document.body).on('click', '#altID', function(){
utag.view({
"page_name": $(this).text(),
"my_url": utag.data['dom.url'] + $(this).attr('href'),
"my_path": utag.data['dom.pathname'] + $(this).attr('href')
})
})`
See both in action over here at CodePen.
So if I have a customer lookup fragment form (i.e. name to lookup and displays address), then need a page with a from and to customer, is there a way to isolate the data binding so that both can be individual?
Currently I can only get the same data to show up in either and so changing one effects the other.
You can override page fragment's datasource:
Once you check 'Override page fragment datasource' checkbox, datasource property will become editable.
Ah got it! In part to what #Pavel responded with....
So in the fragment, the data source is set up pretty much normally:
In the inserted fragments, settings are as follows:
- over-ride checked
- datasource: #Datasources.Addresses.items
Both fragments now act individually on selected name.
Note: In order to demonstrate the below issue, I've created an example in Plunker. In there, I'm using a mock server due to the flaw of the writable service from odata.org. Nevertheless, the issue is reproducible with a real server as well.
Currently, I'm binding a child collection to a list relative to an expanded single entity through a navigation property. Something like this:
<Page title="Products"
binding="{
path: 'odataModel>/BusinessPartnerSet(\'0100000000\')',
parameters: {
expand: 'ToProducts'
}
}"
>
<List items="{odataModel>ToProducts}">
<StandardListItem title="{odataModel>ProductName}" />
</List>
</Page>
Now, if I delete an item from the list, the ListBinding sends a batch request containing DELETE and GET. Here is a screenshot of the batchRequestSent event:
The deleted item is gone from the ListBinding and the list is updated as expected. If I have an additional list with the same bindings, then that additional list gets also updated because of the TwoWay data binding (like the Plunker example above). So far so good.
Problem
But the problem is: The parent ContextBinding (in this case, the element binding of the Page) is not updated. This can be seen if you call bindingContext.getProperty("ToProducts") and it will return a list of binding paths in which the ones of the already deleted items are still there. I guess this is because there was no GET request sent from the ContextBinding but from the ListBinding only.
My question
If the change took place in the child ListBinding (either through DELETE or CREATE), how can the parent ContextBinding get notified about the change and update itself without sending an additional request, so that bindingContext.getProperty("ToProducts").length returns always the correct length?
Or differently, when the change occurs, how can I prevent UI5 from sending a GET request from the child ListBinding and let it send the request from the parent ContextBinding instead, so that the change gets propagated to the child ListBinding afterwards automatically?
Is there any standard approach to solve this kind of problem in UI5?
PS: The same problem does not apply to JSON-based bindings. It seems to be OData only.
If someone encounters the same issue: it turned out to be a bug in UI5 which is fixed in 1.46.7+.
[FIX] ODataListBinding: Update expanded list array
If the fix is not available in your current release, one workaround would be to refresh the parent binding by calling parentControl.getElementBinding("modelName").refresh(false, "yourDeferredGroupId") so that the GET request can be sent together with the DELETE request in a single batch request.
Additionally, we can turn off refreshAfterChange (as krisho suggested) so that UI5 doesn't append yet other GET requests for corresponding ListBindings (relatively bound as well as absolutely bound ones). A disadvantage of this approach is that the absolutely bound ListBinding (which has the same content as the relatively bound one) has to be refreshed manually as well - if there is any.
To stop the framework from making the 'GET' call after Delete, you can use the property 'refreshAfterChange' on sap.ui.model.odata.v2.ODataModel, which can be set to 'false'.
After the success of 'Delete', you can 'refresh' the binding on the page, so that all bindings are consistent.
I want to make a view, that can show a single blog post. This is to be used in a panel.
Is it possible to create a view, that show a node getting the node id from the url?
I have tried creating a view with :
CONTEXTUAL FILTERS -> nodeid -> WHEN THE FILTER VALUE IS NOT AVAILABLE
->Provide default value -> Content ID From URL
This does not seem to work though, maybe the URL to the panel holding the view is constructed wrong?
1) If the panel page is a node template override it will have no problems and it will work without extra settings (you will see that also when you set the panel pane, there are not extra settings).
2) If not (eg if it is a frontpage panel page) you have to pass the argument from panel to views. The path for that page should have a nid argument or a panel pane may have this. Eg your path may be "home/%node". And you have to add a context to your panel that is of type node. Then Assign the Node: id to this argument.
See a similar discussion at https://drupal.stackexchange.com/questions/63538/how-to-pass-a-nid-to-panel-and-load-a-node-with-the-given-nid-as-context
I have setup a content rule that gets triggered when I change the state of a dexterity object through the web interface, but when I change the state programmatically the content rule is not triggered.
I use the typical workflow_tool.doActionFor for changing the review_state. The review_state in the catalog/object appears changed to the new state.
Any clues??
I'm using plone 4.2.5 and dexterity 1.2.1.
This is the code I use to change the state:
cart = brains[0].getObject()
wftool = getToolByName(self.context, 'portal_workflow')
wftool.doActionFor(cart, 'charge')
wftool.doActionFor(cart, 'pay')
modified(cart)
Finally I found out that triggering only one transition at a time, plone fires the content rule as expected.
Therefore in my case I setup a workaround in the following way:
The states are: created -> charged -> paid, and the content rule fires when changing to state paid. Sometimes I must change the state from created to paid in one transaction. I enabled the pay transition from state created bypassing the intermediate state charged. So, I only need to trigger one transition to pay a created object, and the content rule works.