hide some fields in a XWiki page - xwiki

I've attached an object to an XWiki page. Now when the page is displayed, all the attributes of the object are displayed in the page too. I don't want to dispaly all the fields, how do I hide some of them?

Short answer: if you want to modify how an object is displayed in an XWiki page, you can edit the class sheet for this.
Longer anser: Assume that the object if of class BarClass in Space Foo, or short in Foo.BarClass. This class page, which defines what fields your objects have, has two accompanying pages, the class template at Foo.BarTemplate, and a class sheet Foo.BarSheet, which contains the code to display objects of this class. You want to look into the sheet.
This can be done by opening the page in the wiki editor, e.g.
http://localhost:8080/xwiki/bin/edit/Foo/BarSheet?editor=wiki
You will see a code like:
{{velocity}}
## You can modify this page to customize the presentation of your object.
## At first you should keep the default presentation and just save the document.
#set($class = $doc.getObject('Foo.BarClass').xWikiClass)
#foreach($prop in $class.properties)
; $prop.prettyName
: $doc.display($prop.getName())
#end
{{/velocity}}
If you want to hide, say field2, you can do this by changing the foreach loop to:
#foreach($prop in $class.properties)
#if ($prop.name != 'field2' || $xcontext.action == 'edit')
; $prop.prettyName
: $doc.display($prop.getName())
#end
#end
The $prop.name != 'field2' makes sure the field is not shown if that field's name is field2 and the $xcontext.action == 'edit' takes care that your field is still shown in the edit mode (otherwise your users will not be able to edit the field, which is probably not what you want).
If instead you have created your class with the AppWithinMinutes, the class sheet looks differernt:
{{velocity}}
{{html wiki="true"}}
#set ($discard = $doc.use('FooBarCode.FooBarClass'))
#set ($discard = $services.localization.use('document', 'FooBarCode.FooBarTranslations'))
(% class="xform" %)
(((
; <label for="FooBarCode.FooBarClass_0_field1">$escapetool.xml($doc.displayPrettyName('field1', false, false))</label>
: $doc.display('field1')
; <label for="FooBarCode.FooBarClass_0_field2">$escapetool.xml($doc.displayPrettyName('field2', false, false))</label>
: $doc.display('field2')
; <label for="FooBarCode.FooBarClass_0_field3">$escapetool.xml($doc.displayPrettyName('field3', false, false))</label>
: $doc.display('field3')
)))
{{/html}}
{{/velocity}}
In that case you need to find the two lines displaying the field you want to hide, and wrap then into a simple #if ($xcontext.action == 'edit') like:
#if ($xcontext.action == 'edit')
; <label for="FooBarCode.FooBarClass_0_field2">$escapetool.xml($doc.displayPrettyName('field2', false, false))</label>
: $doc.display('field2')
#end
If you want to know more about how XWiki classes are used, read the tutorial at http://platform.xwiki.org/xwiki/bin/view/DevGuide/FAQTutorialManual
Usually you want to create and manage your wiki classes via the "App within minutes" application: http://extensions.xwiki.org/xwiki/bin/view/Extension/App+Within+Minutes+Application which creates an user friendly interface, but for customizations like the one you wanted, you need to edit the sheet directly.

Related

CKEditor 5 copy selected content from one editor to another

I have two editors on the screen, one read-only. What I want to do is allow the user to select content from the read-only editor and paste it into the current position of the other by clicking a button. (the logic may manipulate the text which is one reason I don't want to use the system's clipboard.)
So far I have the function that is able to paste the text like as follows. (I am using the Angular wrapper which explains the presence of the CKEditorComponent reference.
doPaste(pasteEvent: PasteEvent, editorComponent: CKEditorComponent) {
const editor = editorComponent.editorInstance;
editor.model.change(writer => {
writer.insertText(pasteEvent.text, editor.model.document.selection.getFirstPosition() );
});
}
What I can't find from the documentation is how to extract the selected text. What I have so far is:
clickPasteSelectedPlain(editorComponent: CKEditorComponent) {
const editor = editorComponent.editorInstance;
const selection = editor.model.document.selection;
console.log('clickPasteAll selection', selection);
console.log('clickPasteAll selectedcontent', editor.model.document.getSelectedContent);
}
The selection appears to change depending on what is selected in the editor's view. The getSelectedContent function is undefined. How do I get the content?
With a bit of poking around I figured out how to do this. I'll document it here on the chance that it will help someone down the road avoid the process of discovery that I went through.
On the source document I have a ckeditor element like this:
<div *ngIf="document">
<ckeditor #ckEditor
[editor]="Editor" [config]="ckconfig" [disabled]="true"
[(ngModel)]="document.text"></ckeditor>
<button mat-flat-button (click)="clickPasteSelectedPlain(ckEditor)">Paste Selected Text Plain</button>
</div>
In the component the function called on the click event is like this:
#Output() paste = new EventEmitter<PasteEvent>();
...
clickPasteSelectedPlain(editorComponent: CKEditorComponent) {
const editor = editorComponent.editorInstance;
this.paste.emit({
content: editor.model.getSelectedContent(editor.model.document.selection),
obj: this.document,
quote: false
});
}
The PasteEvent is defined as an exported interface which I will omit here to save space. The content key will refer to a DocumentFragment.
Note that I am passing the CKEditorComponent as a parameter. You could also access it via an Angular #ViewChild declaration but note that my ckeditor is inside an *ngIf structure. I think that works well in Angular 6 but in the past I have had difficulty with #ViewChild references when the target was conditionally in the DOM. This method always works but use whatever method you want.
The event fired by the emit is processed with a method that looks like this:
doPaste(pasteEvent: PasteEvent, editorComponent: CKEditorComponent) {
const editor = editorComponent.editorInstance;
editor.model.insertContent(pasteEvent.content);
}
Because the content is a DocumentFragment the paste operation will include all formatting and text attributes contained in the selected source. But that's all there is to it.

Modifying column header names in Master-Detail grid in Devexpress

I have a Master-Detail set up with 2 grids. On the master grid, I have the ShowOnlyPredefinedDetails option set to false.
This means that I see a little + sign that allows me to expand the details of the detail grid (in the master grid). I would like to rename
some columns in that section as well as hide certain columns. I'm using VB.NET How do I go about this. See image.
You can accomplish this by using the grid control ViewRegistered event, from there you can modify the columns in that grid view that have columns within them that you want to modify, rename, or remove. Here is an example, I hope that it helps:
private void myGridControl_ViewRegistered(object sender, DevExpress.XtraGrid.ViewOperationEventArgs e)
{
if (e != null)
{
if (e.View != null)
{
//Inside of this statement you can adjust, add, and modify all of the columns inside of that grid that appears when you click on the +
(e.View as GridView).Columns["myHiddenColumn"].Visible = false;
(e.View as GridView).Columns.Add(new GridColumn() { Name = "AddColumn", Caption = "Name To Display", Visible = true, FieldName = "DataField"});
(e.View as GridView).Columns["DataField"].OptionsColumn.AllowEdit = false;
(e.View as GridView).Columns["DataField"].OptionsColumn.AllowFocus = false;
(e.View as GridView).Columns["DataField"].OptionsColumn.ReadOnly = true;
}
}
}
I think all you need to do is create a second grid view for your details. If you haven't already done this, do the following:
In your grid designer, click "Retrieve Details" if you have not already done so. This will cause the designer to recognize that you have a second level in your bound object:
Once you see the second layer, now you need a new grid view for it. Click on "Click here to change view" and select "Create a new view" and pick "GridView."
Now you will see both grid views from the designer, and clicking on one or the other will change the context of the menus to the left:
For example, if you have gridView2 selected, when you click on the "Layout" menu, it will show the current layout for your detail grid rather than the master grid. From here, you can remove or add columns as you see fit. Likewise, from the "Columns" menu you will see the new columns (you may have to add them to the view by dragging them over), and you can change the Caption property to change the text of the title.
I suggest you use the Data Annotation attributes with properties of your data-classes to declare how you data should be displayed in GridControl:
To skip column generation for the specific property you can mark this property with the <DisplayAttribute(AutoGenerateField := false)> declaration.
To prevent column from displaying you can mark this property with the <DisplayAttribute(Order := -1)> declaration. Later, user can show this column via Column Chooser UI.
To specify the column caption use the <DisplayAttribute(Name := "YOUR CAPTION")> declaration.
You can also control filtering/editing/formatting and validation capabilities.
Related Links:
Tutorial: Create and Manage Data in Code and Apply Data Annotation Attributes
Video Tutorial: Create and Manage Data in Code and Apply Data Annotation Attributes

FluentBootstrap - Acces to the form object from partial views

I have a view that renders a form with code similar to the following:
#using( var form = Bootstrap.Form().SetHorizontal( 3 ).AddCss( Css.ColSm8, Css.ColMdOffset2 ).Begin() )
{
#form.DisplayFor( m => m.Name )
// bla bla bla
#Html.Action( "Details", "Fare", new { entity = Model.FareId } )
}
How can I access the form object in the partial view, so that the same layout is applied to the whole form?
A lot of work was spent ensuring that the Bootstrap control stack would carry-over into partial views. You have two options here:
The first is to just pass the form object to the partial/action as part of the model. In your case, you would just add it as another property in the anonymous model object you're sending to the action.
You don't need to use the form instance to make FluentBootstrap recognize you're in a form. It's just a convenience to make calling the extensions appropriate to a form easier. You can also just call something like Bootstrap.DisplayFor(x => x.Name) right from the global Bootstrap object in your partial and it will respect any settings you've placed in the containing form defined in the containing view.

Check Word Doc for Field Code before applying

So I've coded a VSTO addin using vb.net to add a header to a document in Word however from historical methods we have lots of templates with field codes. My addin does not account for these and simply strips the header to add xxxxx value you choose from the pop up.
I need my code to be smart enough to 'spot' the field code and append or if it does not exist e.g. a blank document then continue running as expected. I can append this field code using the below code:
wordDocument.Variables("fieldname").Value = "xxxx"
wordDocument.Fields.Update
However my tool then adds the header as normal and strips most the content from the template. So effectively my question is how would I code a check for this before proceeding. So in plain English I would need my addin to go from this:
Load pop up
Set xxxx value in header
Close
To this:
Load pop up
Check Document for existing "fieldname"
If "fieldname" exists then
wordDocument.Variables("fieldname").Value = "xxxx" (from pop up selection)
wordDocument.Fields.Update
However if "fieldname" doesn't exist then continue as normal....
Sorry if this is a little complex and/or long winded.
Thanks in advance.
Here is my code in C#, hope this might help you to code in VB.Net
foreach (Section sec in doc.Sections)
{
doc.ActiveWindow.View.set_SeekView(WdSeekView.wdSeekCurrentPageHeader);
foreach (HeaderFooter headerFooter in sec.GetHeadersFooters())
{
doc.ActiveWindow.View.set_SeekView(headerFooter.IsHeader ? WdSeekView.wdSeekCurrentPageHeader : WdSeekView.wdSeekCurrentPageFooter);
if (headerFooter.Range.Fields.Count > 0)
{
//Append to existing fields
UpdateFields(headerFooter.Range.Fields);
}
else
{
//Add field code
AddFieldCode(headerFooter.Range);
}
}
doc.ActiveWindow.View.set_SeekView(WdSeekView.wdSeekMainDocument);
}
Extension method to iterate through the header types
public static IEnumerable<HeaderFooter> GetHeadersFooters(this Section section)
{
List<HeaderFooter> headerFooterlist = new List<HeaderFooter>
{
section.Headers[WdHeaderFooterIndex.wdHeaderFooterPrimary],
section.Headers[WdHeaderFooterIndex.wdHeaderFooterFirstPage],
section.Headers[WdHeaderFooterIndex.wdHeaderFooterEvenPages],
section.Footers[WdHeaderFooterIndex.wdHeaderFooterPrimary],
section.Footers[WdHeaderFooterIndex.wdHeaderFooterFirstPage],
section.Footers[WdHeaderFooterIndex.wdHeaderFooterEvenPages]
};
return headerFooterlist;
}

Something like .NET's "tag" property for Interface Builder

I'm currently struggling to use UI elements in Interface Builder. I keep trying to do things "in the .NET way."
I have several buttons that all map down their TOUCH event to the SAME FUNCTION:
-(IBAction) onTouch:(id) sender
{
// do something with touch, DEPENDING ON WHAT BUTTON WAS PUSHED
// I want to do something like
if( sender.tag == "something" )
{
//...doesn't work on apple, of course..
}
}
I want to uniquely identify each BUTTON USING SOMETHING like the TAG property in .NET. I tried using the INTERFACE BUILDER "NAME" field that is on the "Identity" panel of interface builder, but I don't know how to access that field programmatically.
-(IBAction) onTouch:(id) sender
{
// do something with touch, DEPENDING ON WHAT BUTTON WAS PUSHED
// I want to do something like
if( sender.InterfaceBuilderName == "something" )
{
//...doesn't work..
}
}
So, WHAT / IS THERE a way to uniquely identify a UI element (such as a button) OTHER THAN doing something like
-(IBAction) onTouch:(id) sender
{
// look at
[sender currentTitle]
}
The reason that's bad is because if the text on the button changes for some cosmetic reason you break the whole app, right
The last solution I can think of is write seperate functions for each button's touch event but I really want to know if it is possible to uniquely identify a button by something similar to .Net's TAG property.
In the iPhone SDK all UIView objects have a property also called tag which is an integer value and can basically be used to do what you are intending.
I usually define a constant for the tag values I'm going to use for a specific purpose.
You can access the tag on the button object:
myButton.tag = MYBUTTON_TAG_CONSTANT
// button tag constant
#define MYBUTTON_TAG_CONSTANT 1
For buttons, there is a Tag entry in the View section (click on your button, select Attributes Inspector from the Tools menu). You can then use this integer value in your code.
Here is a link that may help as well:
http://www.iphonedevsdk.com/forum/iphone-sdk-development/25582-using-tags-interface-builder.html
UIView's tag property is accessible from Interface Builder. Unlike .NET, it's an integer rather than a string.