I'm working on a client project that uses UIPageViewControllers.
The app has a hierarchy of "collection" view controllers that the user navigates through to get to (in this case) a page view controller that contains pages of content.
My design is to have the hierarchy of "collection" view controllers be custom subclasses of UIViewController that know how to manage collections of child view controllers with the client's desired UI.
My view controller that displays a page view controller is a subclass of my parent collection view controller, and that parent view controller class might manage page view controllers, cover-flow style view controllers, table view controllers, or a variety of others.
Ok, so I can't make my view controller that manages a page view controller a subclass of both my parent view controller and of UIPageViewController.
This is an iOS 6 project, so I decided to make my view controller contain a page view controller using an embed segue. That handles the housekeeping of parent/child view controllers painlessly, or so I thought.
However, the client wants a page curl transition in the view controller, and it seems that you can't change the transition of a page view controller after initializing it, nor can you specify the navigation orientation, spine location, etc.
Hmm. Seems I am in a catch 22.
Does anybody know of a way to use an embed segue to embed a page view controller as a child of another view controller and control the settings you get with initWithTransitionStyle:navigationOrientation:options: ?
At this point I might need to abandon the embed segue and manage the parent/child view controller relationship manually, which is a fair amount of work, especially when you deal with forwarding auto-rotation and other messages from parent to child.
Ok, problem solved.
There ARE settings in IB for a UIPageViewController that let you control the transition style, navigation orientation, and options.
The problem is that when I created a container view in my parent view controller, IB created a generic UIViewController as the child and I changed it's type to UICollectionViewController. When I did that the settings stayed those for a generic UIViewController.
I had to delete the generic child UIViewController that IB created, drag a UIPageViewController scene into the storyboard, then control-drag from the collection view onto my new UIPageViewController and select "embed" as the type of segue I wanted. When I did THAT, it gave me the settings I needed.
Related
I'm currently developing a WPF application using the MVVM framework. And I have this functionality:
I have a main window which has a combo box and frame (where I put my pages) and a view model. One of the pages in that frame is where a user can add a data and these data are used to populate the combo box in the main window. My problem is how to automatically update the items in the combo box after adding a data from that page. Btw, this page has a different view model too.
Thanks.
You can establish an event in the page viewmodel for changed data. Then subscribe to those events within the window viewmodel and update the combobox items accordingly.
You have access to the parent window from iframe via window.top. You have to write this code in your page what you have loaded in iFrame.
window.top.document.getElementById("combobox_element_id").value='Your New Value';
best of luck
You can pass the Source DataContext of ComboBox (ObservableCollection) to page ViewModel so you can simply modify the collection from Page view model.
What is the best way to switch to a different view when user navigates to a different url. In angular there is ng-view that takes care of this and inserts corresponding templates and in ember its all route based.
Is it better to just hide other views elements on routing using css or destroying other views and inserting current view?
EDIT
It would be great if someone could give an example how to re-render the view on navigating back to it again and restoring its previous state.
Eg.
if you have a check-box in a view that user can select to add some item to the cart , but in the middle he/she moves to some other url and then comes back, that check-box should be checked.
I would have a main content view with subviews and call remove on it, which is responsible for cleaning up any subviews too (calling remove on them first and going up the hierarchy tree). The concept of subviews doesn't come for free with backbone but isn't hard to implement. And finally attach a new content view.
This ensures you can cleanup and the browser is using a consistent amount of resources.
I would abstract this into some kind of layout view which has a content subview and a function like setContent(view) which handles the remove of any existing content view and the attach of the new one.
Personally I would have a router with sub routers in modules, e.g. a main router which finds a route starting with "checkout" and passes it over to a sub router in the checkout module which is responsible for attaching a new content view.
In Backbone the implementation is up to you which is both good and bad, depending on how nice you do it ;)
Always remove the view as opposed to just hiding it. If you don't remove (and unbind) your views properly, all bindings, handlers and references to models/DOM elements will linger around.
Depending on the size of your app, you can have a module that handles layouts (as suggested by dominic-tobias), or have a method on the router that takes care of this for you. At its most basic, this method (let's call it _switchView) takes a view and holds onto an instance of the currentView. Upon view change, it removes the current view, sets the new view to the current view and then renders it to the DOM.
Something like this:
_switchView(view) {
this.currentView && this.currentView.remove();
this.currentView = view;
this.$rootEl.html(view.render().$el);
}
I am using a splitviewcontroller template. From the detail view I am navigating to a different view controller using a SEGUE. The problem is the new view only displays in the detail view part of the split view. I want the new view to cover entire screen or a way to completely remove master view (when new view is pushed) and push master view back later. How can i do that ?
some code examples would be helpful.
You can implement this delegate method to conditionally hide the master view:
- (BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController (UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation
{
return YES;
}
I'm pretty new to Backbone and Marionette and am having a tough time getting my views to communicate.
I've got a composite view that displays a list of items. To add a new item to the list, I have a popup modal that opens in a new item view that is separate from the composite view.
I'm not sure that this is the best way to do this, but in the modal, I created a new instance of the collection with all of the items and added the new item to that collection. This new item shows up in the original composite view, but only after I refresh the page.
I can't seem to figure out how to get the composite view to listen for the add event and render the new model after it is added.
Am I on the right track here? If not, what should I be doing to add to a collection from a modal?
I think I got this figured out. Instead of creating a new collection in the modal view, I passed in the collection from the composite view as a parameter when I created the modal view. Now, when I add a new model in the modal, the 'add' event is automatically triggered on both versions of the collection and the view automatically renders the new model. No need to bind any extra events like I was thinking.
Your solution will work, but means your views are pretty tightly coupled. You might want to look into using events instead (see How do I send a model that was clicked on within a ItemView to another ItemView that is on the same page?)
How your functionality would work with events:
Within the modal, you enter the data for the model to create
When you press the "save" button,
you validate and save the model var myNewModel = ...
you trigger an event: MyApp.MySubApp.trigger("item:add", myNewModel)
In the controllerfor the list view, you listen to that event, and add the new model to the collection.
The handler code in your controller would look something like:
MyApp.MySubApp.on("item:add", function(model){
this.myCollection.add(model);
});
If you'd like to learn more about using events, check out 2 Marionette tutorials I wrote:
http://davidsulc.com/blog/2012/04/15/a-simple-backbone-marionette-tutorial/
http://davidsulc.com/blog/2012/05/06/tutorial-a-full-backbone-marionette-application-part-1/
Both use events to communicate information within the apps.
In addition, basic events are also explained here: http://samples.leanpub.com/marionette-gentle-introduction-sample.pdf
I'm trying to learn Backbone from someone else's Backbone app in combination with the documentation. There are two things I don't understand about it that I can't figure out from the documentation. Hope someone might be able to explain...
Gist of the app
It's an app where you can drag and drop company names into boxes.
The app has a Company View, a Company Model and a Companies Collection.
It also has a Bucket View, a Bucket Model, and Buckets Collection
It also has a general App View that's not associated with any model.
Problems...
First- Is it weird that a view would never be rendered?
The App View is instantiated like this
window.App = new AppView();
and it gets different things going in the app (populating the buckets with company names etc and setting up some events). However, the App View is never rendered. The Bucket View and the Company View, on the other hand, are both rendered at different points in the code. For example,
var view = new BucketView({model: bucket});
this.$("#bucket-list").append(view.render().el);
But never that App View. This App View also has no render function. So is it weird that it has a View that's never rendered? Should its code be somewhere else?
Second Considering that App view is never rendered, is there any reason why they would have to change the default setting of el to the name of the main container div in the layout? For example, in the App view, they do this...
el: $("#mainapp"),
However, if this view's never rendered, is there any reason to change the default setting of el?
When you create a Backbone.View instance normally, it will immediately generat an el on the view for you. This is used as the placeholder for all of the HTML that the view will manage, and you generally populate the view's el with your HTML in the render method, as you've already noted.
In some cases, though, you don't want to render a completely new set of HTML elements. Instead, you'll want to manage some existing HTML that's already part of the DOM. In this case, you can easily attach a backbone view to the existing DOM element by specifying the el in the constructor, as you've shown with the el: $("#mainapp") line.
When a Backbone view sees that it already has an el, it does not generate it's own. Instead, it uses what it was handed.
So, to directly answer your two questions:
1) First- Is it weird that a view would never be rendered?
No, because ...
2) if this view's never rendered, is there any reason to change the default setting of el?
The question is slightly off in a manner that that can't be directly answered. In reality, the view is never rendered because they are setting the el in the call to the constructor.