knockout js jquery Load - javascript

Hi I am trying to load knockout js html pages dynamically from jQuery Load but getting
You cannot apply bindings multiple times to the same element.
How do I load knockout js pages with jqyuery load.
What I am trying is to create a navigation framework by loading url page (Views/home.html or Views/login.html)into when ever user click on link.
So I can't load all knocokout viewmodel on fist load
I am trying to create Navigation model to load/refresh only body of the page not the full page.
For example
<ul class="nav navbar-nav" id="nav">
<li>
Home
</li>
<li>
Login
</li>
<li>
Contactus
</li>
</ul>
<div id="body"></div>
if Home click
$("#body").load("Views/home.html");
if Login click
$("#body").load("Views/login.html");
Home.html
var homeViewModel= function() {
this.firstName = ko.observable();
this.lastName = ko.observable();
};
ko.applyBindings(new homeViewModel());
Login.html
var loginViewModel= function () {
this.username = ko.observable("test");
};
ko.applyBindings(new loginViewModel())

I have attached and removed node but the dependency is always name of viewmodel must be viewModel
ko.cleanNode($("#body")[0]);
$("#body").load(url, function() {
ko.applyBindings(new viewModel(), $("#body")[0]);
});

You may want to look at Pager.js, which extends knockout.js for page history and partial loading.
Load all your javascript in your main page.
Keep the partials (Views/home.html, Views/login.html) containing only html with binding declarations.
You don't need to explicitly call applyBindings when switching partial, Pager.js does that for you (with proper cleanup for all bindings on previous partial).

Related

ng-repeat when data is ready

I have a website with two webpages:
A settings page: webpage with JSON content that looks like this:
{"Sources":["1","2","3","4"]}
A webpage that present all the known "sources" in the system. Just print them one after another.
When my application loading, I downloading the sources page, and save in on my scope at $scope.Settings.Sources.
My AngularJS code:
$scope.getSettings = function (ID, successCallback, failureCallback)
{
$scope.ID = ID;
$http.get("/sources?ID=" + ID).then(function (response)
{
if (response.status == 200)
{
$scope.Settings = response.data;
successCallback();
}
else
{
failureCallback();
}
});
}
function getSettings_success()
{
// Ready to update the ng-repeat NOW.
}
function getSettings_error()
{
alert('Error');
}
$scope.getSettings(1, getSettings_success, getSettings_error);
Now, when i have the $scope.Settings.Sources ready, all I have to do is to print each soruce in specific HTML template. Because of that, I was thinking to use the ng-repeat for this task. Something like this:
<div ng-init="sources=$scope.Settings.Sources">
<ul>
<li ng-repeat="source in sources">
{{ source }}
</li>
</ul>
</div>
Unfortunately, this code isn't working. This because when the page is loading, the $scope.Settings.Sources isn't ready yet. So, the ng-repeat must run after the "sources" page was downloaded.
Is this possible? If yes, how?
You shouldn't be using ng-init for such case, because data is coming by Ajax and you are assigning blank object to source. Cause doesn't responded yet. Rather I'd use Settings.Sources variable directly on your view.
Markup
<div>
<ul>
<li ng-repeat="source in Settings.Sources">
{{ source }}
</li>
</ul>
</div>
Side Note: $scope variable's directly accessible inside angular directives, you don't need explictly specify $scope

Ember.js Render multiple views inside static HTML

I'm new to Ember and I'm stuck trying to render views.
The application in context is not a single page application but so far Ember has been playing nice until I started dealing with views.
I'm trying to render more than one view on a single page (which is like a dashboard and has tons of static HTML and a few containers, one for each view).
Sample HTML:
Let's say I would like to render two lists, one inside the "left-container" div and the other inside the right container.
<div class="static-header></div>
<!-- more static content goes here -->
<div id="left-container"></div>
<!-- more static content goes here -->
<div id="right-container"></div>
...
I've tried creating different views and inserting them using the appendTo method (which is described in the Defining a View section of Ember guides) but it throws the error:
Container was not found when looking up a views template. This is most likely due to manually instantiating an Ember.View. See: http://git.io/EKPpnA
and I couldn't find my way using the link that it points to.
Ember code:
var App = Ember.Application.create({});
App.HomeViewLeft = Ember.View.extend({
templateName: 'home-left',
});
var view = App.HomeViewLeft.create();
view.appendTo('#left-container');
I have also tried using a ContainerView as described in Ember api docs:
App.HomeViewLeft = Ember.View.extend({
templateName: 'home-left',
});
var containerView = Ember.ContainerView.create({
classNames: ['container-view'],
});
containerView.pushObject(App.HomeViewLeft.create());
containerView.appendTo('left-container');
But I get the same error.
How should I render each view inside the #left-container and #right-container respectively?
Thanks in advance.
Template:
<div id="here"></div>
<script type="text/x-handlebars" data-template-name="components/my-foo">
{{text}}
</script>
JS:
App = Ember.Application.create({});
Ember.Application.initializer({
name: 'stand-alone-components',
initialize: function(container, application) {
App.MyFooComponent.create({text: 'Hello World', container: container}).appendTo('#here');
}
});
App.MyFooComponent = Ember.Component.extend({
init: function() {
this._super();
this.set('layout', Ember.TEMPLATES['components/my-foo']);
}
});
http://emberjs.jsbin.com/nekowidera/1/edit?html,js,output
It looks like you are trying to make views behave like partials
Move anything static into a partial and include it in your main template like so:
{{partial "header"}}
The lists you want to render can be turned into a component (if the only thing that changes in them is the data).
So you end up with a single view that contains partials and components:
<div class="static-header>{{partial "header"}}</div>
{{partial "static-content"}}
<div id="left-container">{{list-component data=firstList}}</div>
{{partial "static-content"}}
<div id="right-container">{{list-component data=secondList}}</div>
...

Implementing a master view with multiple collections. Backbone.js

EDIT my humble mockup of what I want to implement
I have defined such a view:
define(['jquery', 'underscore', 'backbone', 'text!_templates/gv_container.html', 'bootstrap/bootstrap-tab'],
function($, _, Backbone, htmlTemplate, tab) {
var GridViewContainer = Backbone.View.extend({
id: 'tab-panel',
template: _.template(htmlTemplate),
events: { 'click ul.nav-tabs a': 'tabClicked' },
tabClicked: function(e) {
e.preventDefault();
$(e.target).tab('show');
},
render: function() {
this.$el.append(this.template);
return this;
}
});
return GridViewContainer;
}); // define(...)
The view's template looks like this:
<ul class="nav nav-tabs">
<li class="active">Products</li>
<!-- other tabs -->
</ul>
<div class="tab-content">
<div class="tab-pane active" id="products">
<!-- table with rows like { title, few more properties, edit|remove links } -->
</div>
<!-- other panes ... -->
</div>
Initially I thought I might use it (as common template for all collections at once).
Goal
I have three collections: products, categories, orders. And I want to insert each of them as tables on separate tab-panes. As for passing models to GridViewContainer I think I can wrap them in a composite model and simply pass the latter one as a part of options object to GridViewContainer view. What's next?
Product, Order, Category models have different properties, have different edit forms and probably event handling. This brings specificity. Should I use [EntityName]ListView per collection and then append it to GridViewContainer view?
ASIDE
I use jquery.js, underscore.js, backbone.js, require.js, and ASP.NET MVC 4 on server side.
I don't use Marionette.js
I would recommend to create a view for each model.
You may create a abstract wich holds the shared stuff like table creation.
Each view extends your abstract instead of Backbone.View.
var myAbstract = Backbone.View.extend({...})
var productsView = myAbstract.extend({...})
Then create a view, handling the wrapper (Tabs).
Example: http://jsfiddle.net/DC7rN/

how to implement dynamic breadcrumb

I want to implement dynamic breadcrumb and really dont know how do i go about it. Cant find much examples on internet. Please see attached image where i have added breadcrumb. The code for it as below
<div style="font-size: 10px;">
<ul class="breadcrumb">
<li>
Home <span class="divider">></span>
</li>
<li>
<li><a id="navObject" href="../AgrProduct/Index.aspx" class="active" >Search</a></li>
</ul>
</div>
Currently i have just 2 level in breadcrumb as Home and Search. when i click on button Search it will show me list of products and when i select one on product the breadcrumb should show as Home > Search > Product. I am also attaching image of what happens when i click on Search button
Please let me know how should i go about it. I am really stuck. I use knockout,jquery.
Well, if you created a breadcrumb view model:
var breadCrumbViewModel = function()
{
var self = this;
self.breadCrumbs = ko.observableArray();
self.addCrumb = function(url, text, active)
{
self.breadCrumbs.push({ 'url': url, 'text': text, 'active': active });
}
self.reset = function()
{
self.breadCrumbs.removeAll();
}
}
And then use it something like this (I've not tested this, so there may be some errors in it, but the idea should be good!)
<ul class="breadcrumb" data-bind="foreach: breadCrumbViewModel.breadCrumbs">
<li>
<a data-bind="attr: { href: url }, text: text, css: { active: active }"></a> <span data-bind="visible: $index < breadCrumbViewModel.breadCrumbs - 1" class="divider">></span>
</li>
</ul>
You would set it up in the function called whenever you navigate to a "page" within your SPA:
function()
{
breadCrumbViewModel.reset();
breadCrumbViewModel.addCrumb('#/Home', 'Home');
breadCrumbViewModel.addCrumb('#/Product/:id', 'Search', true);
}
Don't forget to bind the model the the html element for knockout to do its stuff.
I'm using the example code for sammy.js for the navigation, though I will admit that I haven't used sammy.js before, I've got a custom implementation of navhistory.js from the Microsoft Big Shelf SPA example. But that should be enough to give you a head start on it. I'm assuming that you actually want this to be a SPA, despite having actual URLs in your links that would take you off to another page.

knockout: accessing the View Model through an iframe?

The app I'm building requires the use of iframes for wysiwyg text editing, and these iframes need to be wired up to the viewModel, but I'm finding that this clashes with knockout... or at least knockout seems not to apply bindings when I try to access them through the parent object.
Here's some code...
<script type="text/javascript">
$(function(){
ko.applyBindings(parent.model.project, $('#root')[0]);
});
</script>
<ul id="root" data-bind="template: {name: function(){return type()},
foreach: populate() }"></ul>
<script id="document" type="text/html">
<li class="draft" draft="${draft()}" data-bind="css: {expanded: $data.expanded}">
<span data-bind="click: function(){parent.model.project.expand($data, 'draft')}">
${ordinal(draft())} Draft
<img src="icons/close-black.png"
data-bind="click: function(){parent.model.project.deleteDraft($data)},
css:{ only: function() {parent.model.project.drafts > 1} }"/>
</span>
<div>
<ul data-bind="css: {expanded: $data.expanded},
template: {
name: 'draft',
foreach: $data.draftItems,
}"
>
</ul>
</div>
</li>
</script>
<script id="draft" type="text/html">
{{if $data.name}}
<li class="${name}">${name}</li>
{{/if}}
</script>
OK, this isn't a wysiwyg text editor, but it still illustrates my point.
Now the thing is, when I wrote this it worked perfectly. I had the part of viewModel that all the bindings refer to defined in a js file accessed only by this html... but I need the same ViewModel to be accessed by the parent window, as I would with a wysiwyg editor for toolbar buttons and other external controls, so I moved that part of the viewModel to the file where the rest of it was defined... and now it doesn't work!
In the external file that I had previously I was still accessing the parent view model using parent.model, but now not having direct exclusive access to that model it doesn't seem to work. The thing is though that I can access the view model with console.log, I can document.write from it too, it fires off events back to the viewModel, and my view updates initially, but after that initial one it no longer updates.
Is there a way to solve this?
iframes won't inherit bindings from parent elements.
You can't make it work that way, as iframes really are separate pages within another page.
Each iframe will need to have its own view model. If that viewmodel needs to come from another view model, you'll need to share that data via global JS objects or message passing or some other mechanism.

Categories

Resources