I am building my first app with ST2 and began by building the app outlined in Getting Started with Sencha Touch 2 and then taking that and trying to modify it so it met my own needs. The demo app has a DataView List where each element can be tapped to reveal a corresponding detail page.
In that app the content on the detail pages is being pulled in dynamically and does not need to be styled or arranged much. However, for my own detail pages I need to use a Template or XTemplate to style and position my data.
I can't seem to figure out where I should define the template (ie, var myTpl = new Ext.XTemplate(...)) —In the controller, in the model?
Any guidance on this front would be much appreciated.
This depends on where you want to use the XTemplate. If it is only ever going to be used in one view, then just define the xtemplate when you defined the view.
{
xtype : 'view',
tpl : new XTemplate('<div></div>...')
}
If you are going to use it in multiple views, then you can create a class that has a sole purpose of sharing templates.
Ext.define('MyApp.util.SharedTemplates', {
statics : {
sharedTemplate1 : new XTemplate('<div></div>')
}
});
This way the template only gets compiled once and is re-useable.
Related
I have an Aurelia app where a user can click on a button and create a new tab. The tab and its content (a custom element) do not exist on the page before the user clicks the button. I am generating the HTML for the content at runtime (via Javascript) in my view model.
I keep seeing mention of using the template engine's compose or enhance functions, but neither are working for me. I don't know how I would use the <compose> element (in my HTML) since I am creating the element based on the user clicking a button.
My thought was that the button has a click.delegate to a function that does ultimately does something like
const customElement = document.createElement('custom-element');
parentElement.appendChild(customElement);
const view = this.templatingEngine.enhance({
element : customElement,
container : this.container, // injected
resources : this.viewResources, // injected
bindingContext: {
attrOne: this.foo,
attrTwo: this.bar,
}
});
view.attached();
But all this does is create an HTML element <custom-element></custom-element> without actually binding any attributes to it.
How can I create a custom element analogous to <custom-element attr-one.bind="foo" attr-two.bind="bar"></custom-element> but via Javascript?
As you pointed out in your own answer, it's the missing resources that caused the issue. One solution is to register it globally. That is not always the desired behavior though, as sometimes you want to lazily load the resources and enhance some lazy piece of HTML. Enhance API accepts an option for the resources that you want to compile the view with. So you can do this:
.enhance({
resources: new ViewResources(myGlobalResources) // alter the view resources here
})
for the view resources, if you want to get it from a particular custom element, you can hook into the created lifecycle and get it, or you can inject the container and retrieve it via container.get(ViewResources)
I found the problem =\ I had to make my custom element a global resource.
I would like to have a shared UI project with common interface for other apps, so I don't have to copy/paste the same _Layout.cshtml between all apps which need same UI.
After using this question as reference and this article I have created shared Razor Class Library project. And when I reference this project via NuGet, the _Layout.cshtml in this shared project gets called and renders header with navigation.
But my problem comes then if I want to add some extra HTML to header. Let say I have drop down with some link to main landing page, to user setting, some administration page and etc. But how could I add some extra navigation links specific to concrete app next to all common links? Is there a way to inject HTML? Or maybe to pass some DTO model to this _Layout.cshtml?
Dump image below to help you to see what I try to achieve.
There's two possible approaches. First, you can simply call a partial in your layout:
<partial name="_HeaderExtra" />
Then, just add an empty partial view to the RCL, so it's satisfied, i.e. _HeaderExtra.cshtml. Finally, in your actual application, create the same partial view in the same location as the one in the RCL, and add whatever extra HTML you want there. When the partial is pulled into your layout, it will looking your project first, before falling back to the RCL.
The second option is to use sections. Sections are a little bit more strict, and you must remember to always reimplement them if you do any view inheritance. Essentially, in your layout, at something like:
#await RenderSectionAsync("HeaderExtra", required: false)
Then, in any sublayouts or views:
#section HeaderExtra
{
<!-- add something here -->
}
If you've got a sublayout and you want to be able to further customize this section in views, then you need:
#section HeaderExtra
{
#await RenderSectionAsync("HeaderExtra", required: false)
<!-- add something here -->
}
I am currently developing a web application that is used to display elements for events on a map provided by HERE Maps. I am using Vue.
I have some components, but the relevant component is the component HereMaps.vue which initializes the map using the HERE Maps Api.
The HERE Maps Api provides the possibility to place so called InfoBubbles on the map showing additional information. These InfoBubbles can be provided some HTML-code in order to customize their appearance.
Please refer to the documentation for additional information
Following the documentation the code looks something like this:
let bubble = new H.ui.InfoBubble(marker.getPosition(), {
content: "<div class='someClass'>Some Content</div>"
});
this.ui.addBubble(bubble)
This is happening after mount in the "mounted" method from Vue in the "HereMaps" component.
The Bubbles are added in a "closed" (hidden) form and dynamically "opened" to reveal their content when the corresponding marker icon on the map is clicked. Therefore the HTML-code is present on the DOM after the component is mounted and is not removed at a later stage.
Now instead of supplying custom code within each bubble added to the UI i want to just add a component like this:
let bubble = new H.ui.InfoBubble(marker.getPosition(), {
content: "<myDynamicComponent></myDynamicComponent>"
});
this.ui.addBubble(bubble)
It does not matter to me wether the component is initialized using props or if it is conditionally rendered depending on the state of a global variable. I just want to be able to use the "myDynamicComponent" in order to customize the appearance in a different file. Otherwise the design process gets very messy.
As far as i know this is not possible or at least i was not able to get it work. This is probably due to the fact that the "myDynamicComponent" is not used within the "template" of the "HereMaps" component und thus Vue does not know that it needs to render something here after the directive is added to the DOM in the "mounted" method.
This is what the InfoBubble looks using normal HTML as an argument:
This is what the InfoBubble looks using the component as an argument:
It appears to just be empty. No content of the "myDynamicComponent" is shown.
Does anyone have any idea how i could solve this problem.
Thank You.
Answer is a bit complicated and I bet you wouldn't like it:)
content param can accept String or Node value. So you can make new Vue with rendered your component and pass root element as content param.
BTW, Vue does not work as you think, <myDynamicComponent></myDynamicComponent> bindings, etc exists in HTML only in compile time. After that all custom elements(components) are compiled to render functions. So you can't use your components in that way.
Give us fiddle with your problem, so we can provide working example:)
I'm practically brand new to Aurelia, but over the course of a few days I've picked up the starter template and gone through some video training in Pluralsight. I have a unique vision that I can't seem to decide whether compose element, custom element, or router is best to use for this scenario - or if I need to write something completely custom.
I prefer to continue using the router because it gives you the
URLs and history state. Linking deep within the web app may be necessary.
When a view / viewmodel is initialized, I want the view appended to the DOM, NOT replaced. The <router-view> element works by replacing the view.
With each view appended to the DOM, I would like to create a set of tabs representing every view that has been opened so far. Think of any modern text editor, IDE, or even a web browser shows tabs.
Sometimes it would be necessary to detect whether a view is already rendered in the DOM (viewmodel + parameter) and just bring that view to the front -vs- appending the new one.
Do you have any suggestions, examples, etc for someone relatively new to Aurelia, SPAs, and MVVM?
Thank you.
I believe the easiest way is using the compose element. You would need an array containing all screens, and another array to hold the opened screens. Something like this:
screens = [
{ id: 1, name: 'Test 1', view: './test-1.html', viewModel: './test-1' },
{ id: 2, name: 'Test 2', view: './test-2.html', viewModel: './test-2' }
];
_activeScreens = [];
get activeScreens() {
return this.screens.filter((s) => this._activeScreens.indexOf(s.id) !== -1);
}
In the HTML you just have to use <compose></compose> for each iteration of activeScreens.
I made this example https://gist.run/?id=c32f322b1f56e6f0a83679512247af7b to show you the idea. In my case, I've used an html table. In your case, you could use a tab plugin, like Bootstrap or jQuery.
Hope this helps!
I am attempting to implement the i18n strategy outlined here in my Sencha Touch MVC app. The problem is, this strategy requires an onReady(), which I don't have anywhere in my app. I have an app.js, which defines a launch function. I've got a viewport which creates my various panels in my app's namespace. But creating the Bundle object in either of these doesn't seem to work. Does anyone have any ideas, or maybe a different approach I should be taking to i18n?
Earliest event would be
Ext.setup({
onReady: function() {
...
}
});
That onReady will fire when the dom is ready before your application exists ... but from the example that Ext.i18n.Bundle-touch provides they are calling the bundle.onReady function in the launch function.