I'm evaluating backbone.js, backbone-forms and Rails, and I have some problems ...
I have a view where I create a new model and a form, and I want to display this form with other html elements, so I'm using a template.
expedients_new.js.coffee
------------------------
class Globalbackbone.Views.ExpedientsNew extends Backbone.View
template: JST['expedients/new']
render: ->
#form = new Backbone.Form({
model: #model
}).render();
console.log(#model.procedencia)
console.log(#form)
$(#el).html(#template(expedient: #model, form: #form ))
this
This view uses a template, and in this template, I want to render the form there, but I don't know how to do it ...
new.jst.eco
-----------
<h1>BackBones with GlobalWeb</h1>
<h2>Adding New Expedient</h2>
<%=#expedient.date%>
<hr>
<%=#form.el%>
<hr>
<%=#form%>
Thanks in advance,
regards
EDIT
The current browser output where I expect the form is:
[object HTMLFormElement]
The usage instructions indicate that #form will be a Backbone view:
var form = new Backbone.Form({
model: user
}).render();
and that means that #form.el will be a DOM element that you need to insert into the DOM:
$('body').append(form.el);
And if you look at the source, you'll see that Backbone.Form is a Backbone.View subclass:
var Form = (function() {
return Backbone.View.extend({
//...
Your code is trying to treat #form as though it was a string containing HTML:
<%=#form%>
so you end up with standard stringified version of a DOM element: [object HTMLFormElement].
I think you'll have better luck if you have something like this in your view:
#$el.append(#template(expedient: #model))
#$el.append(#form.el)
and in your template:
<h1>BackBones with GlobalWeb</h1>
<h2>Adding New Expedient</h2>
<%=#expedient.date%>
<hr>
Then your form should appear after the <hr>.
Related
This is my object
var users ={
twitter : {
name : //,
lastname : //
},
facebook : {
name : //,
lastname : //
}
}
}
I have a dynamic variable activeuser that updates from Facebook to twitter.
What i'm trying to do is refer to the inner object in users depending on the value of activeuser. I need to give my div something like this class :
<div class=' {{users.activeuser}}'></div>
I know this is not how it should be done with vue.js. Do you have any suggestions?
Thank You!
Using VueJS you should be able to assign your dynamic variable to a Vue Model when you load the new object using a Vue setter $set('property name', 'value')
Example AJAX retreival:
$.getJSON('myURL.html?query=xxx', function(data, textStatus, jqXHR){
try{
MyVue.$set('dynamicObject', data);
}
catch(e){}
});
A generic Vue may look like this:
var MyVue = new Vue({
el:'#exampleDiv',
data: {
dynamicObject : ''
}
});
Bound to an example HTML element:
<div id="exampleDiv">
<label class="{{dynamicObject.activeuser}}">{{dynamicObject.username}}</label>
</div>
In the case that you have an object with an array of objects which also contain properties Vue makes it very simple to create many HTML elements (for each child object) by simply adding a v-repeat (example) to the desired HTML and assigning the datasource:
<div id="exampleDiv">
<label v-repeat="dynamicObject" class="{{dynamicObject.activeuser}}"></label>
</div>
I have a custom widget which extends _WidgetBase, _TemplatedMixin with template
<div dojoAttachPoint="widget">
<div dojoAttachPoint="title">${name}</div>
<div dojoAttachPoint="dnmschart"></div>
</div>
and another widget which extends above widget
require([
'dojo/_base/declare',
'my/widget/view/AbstractWidget'
], function (declare, AbstractWidget) {
return declare("my.widget.view.AbstractChart", [AbstractWidget], {
constructor:function(){
},
buildRendering: function(){
this.inherited(arguments);
var gridDiv = document.createElement("div");
gridDiv.setAttribute("dojoAttachPoint", "gridPlaceHolder");
},
postCreate:function(){
this.inherited(arguments);
//Here I could not get newly created node gridPlaceHolder
console.log(" POST CREATION");
}
});
});
When I print in console (Break point in post create method)
this.domNode
It shows newly created node at last in document(last node in above template)
<div dojoattachpoint="gridPlaceHolder"></div>
But I could not access gridPlaceHolder attach point in post create method.
Is there anything else need to configure?
Please help me on this:)
data-dojo-attach-point (which you should use for 1.6+ instead of dojoAttachPoint) allows you to have handles for dom nodes in your template.. It is parsed by _TemplatedMixin's buildRendering(), so it will be available in your buildRendering method just after this.inherited line.
You can not set data-dojo-attach-point using setAttribute, it can only be defined in templates to be parsed by TemplatedMixin. If you need your child widget to add some markup in addition to what there is in its parent's template, you can define a variable in your parent's markup, and overwrite it in your child widget:
Your AbstractWidget template:
<div data-dojo-attach-point="widget">
<div data-dojo-attach-point="title">${name}</div>
<div data-dojo-attach-point="dnmschart"></div>
${childMarkup}
</div>
And then you need to add your additional markup in child's buildRendering, before this.inherited:
require([
'dojo/_base/declare',
'my/widget/view/AbstractWidget'
], function (declare, AbstractWidget) {
return declare("my.widget.view.AbstractChart", [AbstractWidget], {
buildRendering: function(){
this.childMarkup = '<div data-dojo-attach-point="gridPlaceHolder"></div>';
this.inherited(arguments);
}
});
As stafamus said, the primary problem here is that you're attempting to assign data-dojo-attach-point or dojoAttachPoint to a node after the template has already been parsed (which happens during the this.inherited call in your buildRendering.
Going beyond that, given the code in the original post, it also appears you're never actually adding the markup you create in buildRendering to your widget's DOM at all - you've only created a div that is not attached to any existing DOM tree. I'm a bit confused on this point though, since you claim that you are seeing the markup for the node you added, which shouldn't be possible with the code above, or the code in stafamus' answer.
Rather than attempting to dump extra markup into your template, you might as well do the programmatic equivalent to what an attach point would be doing in this case anyway: create your DOM node, attach it to your widget's DOM, and assign it to this.gridPlaceHolder. e.g.:
buildRendering: function () {
this.inherited(arguments);
this.gridPlaceHolder = document.createElement('div');
this.domNode.appendChild(this.gridPlaceholder);
}
I use the control MicrosoftNSJS.Advertising.AdControl in the ItemTemplate of a ListView.
I would like to bind some datas to the following data-win-options properties : ApplicationId and AdUnitId
The source datas are correctly set and are visible in my item template, I can display them with an h2 + a classic data-win-bind on innerText property
Ads are displayed correctly if I put directly static IDs in html code but these IDs need to be loaded from a config file...
Is it possible ? Thanks
If it's not possible, can I modify directly the item template in the JS code before to be injected in the listview ?
Come to find out this is possible (I was trying to do something similar)
The syntax for the control properties must be prefixed with winControl.
Example (I'm setting the application id here but binding the html element's className and the ad control's adUnitId)
<div id="adItemTemplate" data-win-control="WinJS.Binding.Template">
<div data-win-bind="className:css; winControl.adUnitId: adUnitId"
data-win-control="MicrosoftNSJS.Advertising.AdControl"
data-win-options="{ applicationId: 'd25517cb-12d4-4699-8bdc-52040c712cab'}">
</div>
</div>
I finally found a way to perform this without real binding, by using the itemTemplateSelector function like this :
function itemTemplateSelector(itemPromise)
{
return itemPromise.then(function (item)
{
if (item.type == "ad")
{
var template = _$(".adTemplate").winControl.render(item, null);
// Access to the AdControl through the DOM
var adControl = template._value.childNodes[1].childNodes[1].winControl;
// Set options that are specified in the item
WinJS.UI.setOptions(adControl, { applicationId: item.AdAppId, adUnitId: item.AdUnitId });
return template;
}
else
{
return _$(".itemTemplate").winControl.render(item, null);
}
}
}
I had this problem in ratings:
<div data-win-control="WinJS.UI.Rating" data-win-options="{averageRating: 3.4, onchange: basics.changeRating}"></div>
I bind it via winControl:
<div data-win-control="WinJS.UI.Rating" data-win-bind="winControl.averageRating: myrating" data-win-options="{onchange: basics.changeRating}"></div>
It worked fine.
<div data-win-bind="this['data-list_item_index']:id WinJS.Binding.setAttribute" >
I'm having problems trying to get the unobtrusive jquery validation to work with a partial view that is loaded dynamically through an AJAX call.
I've been spending days trying to get this code to work with no luck.
Here's the View:
#model MvcApplication2.Models.test
#using (Html.BeginForm())
{
#Html.ValidationSummary(true);
<div id="res"></div>
<input id="submit" type="submit" value="submit" />
}
The Partial View:
#model MvcApplication2.Models.test
#Html.TextAreaFor(m => m.MyProperty);
#Html.ValidationMessageFor(m => m.MyProperty);
<script type="text/javascript" >
$.validator.unobtrusive.parse(document);
</script>
The Model:
public class test
{
[Required(ErrorMessage= "required field")]
public int MyProperty { get; set; }
}
The Controller:
public ActionResult GetView()
{
return PartialView("Test");
}
and finally, the javascript:
$(doument).ready(function () {
$.ajax({
url: '/test/getview',
success: function (res) {
$("#res").html(res);
$.validator.unobtrusive.parse($("#res"));
}
});
$("#submit").click(function () {
if ($("form").valid()) {
alert('valid');
return true;
} else {
alert('not valid');
return false;
}
});
The validation does not work. Even if I don't fill any information in the texbox, the submit event shows the alert ('valid').
However, if instead of loading dynamically the view, I use #Html.Partial("test", Model) to render the partial View in the main View (and I don't do the AJAX call), then the validation works just fine.
This is probably because if I load the content dynamically, the controls don't exist in the DOM yet. But I do a call to $.validator.unobtrusive.parse($("#res")); which should be enough to let the validator about the newly loaded controls...
Can anyone help ?
If you try to parse a form that is already parsed it won't update
What you could do when you add dynamic element to the form is either
You could remove the form's validation and re validate it like this:
var form = $(formSelector)
.removeData("validator") /* added by the raw jquery.validate plugin */
.removeData("unobtrusiveValidation"); /* added by the jquery unobtrusive plugin*/
$.validator.unobtrusive.parse(form);
Access the form's unobtrusiveValidation data using the jquery data method:
$(form).data('unobtrusiveValidation')
then access the rules collection and add the new elements attributes (which is somewhat complicated).
You can also check out this article on Applying unobtrusive jquery validation to dynamic content in ASP.Net MVC for a plugin used for adding dynamic elements to a form. This plugin uses the 2nd solution.
As an addition to Nadeem Khedr's answer....
If you've loaded a form in to your DOM dynamically and then call
jQuery.validator.unobtrusive.parse(form);
(with the extra bits mentioned) and are then going to submit that form using ajax remember to call
$(form).valid()
which returns true or false (and runs the actual validation) before you submit your form.
Surprisingly, when I viewed this question, the official ASP.NET docs still did not have any info about the unobtrusive parse() method or how to use it with dynamic content. I took the liberty of creating an issue at the docs repo (referencing #Nadeem's original answer) and submitting a pull request to fix it. This information is now visible in the client side validation section of the model validation topic.
add this to your _Layout.cshtml
$(function () {
//parsing the unobtrusive attributes when we get content via ajax
$(document).ajaxComplete(function () {
$.validator.unobtrusive.parse(document);
});
});
test this:
if ($.validator.unobtrusive != undefined) {
$.validator.unobtrusive.parse("form");
}
I got struck in the same problem and nothing worked except this:
$(document).ready(function () {
rebindvalidators();
});
function rebindvalidators() {
var $form = $("#id-of-form");
$form.unbind();
$form.data("validator", null);
$.validator.unobtrusive.parse($form);
$form.validate($form.data("unobtrusiveValidation").options);
}
and add
// Check if the form is valid
var $form = $(this.form);
if (!$form.valid())
return;
where you are trying to save the form.
I was saving the form through Ajax call.
Hope this will help someone.
just copy this code again in end of modal code
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
;)
<div dojoType="dojo.Dialog" id="alarmCatDialog" bgColor="#FFFFFF" bgOpacity="0.4" toggle="standard">
<div class='dijitInline'>
<input type='input' class='dateWidgetInput' dojoAttachPoint='numberOfDateNode' selected="true">
</div>
how to show this dialog I tried dijit.byId('alarmCatDialog').show();
The above code is a template and I called dijit.byId('alarmCatDialog').show() from the .js file .
dojo.attr(this.numberOfDateNode) this code works and I got the data .but if I change dojoattachpoint to id then I try dijit.byId('numberOfDateNode') will not work;
Your numberOfDateNode is a plain DOM node, not a widget/dijit, i.e. javascript object extending dijit/_Widget, which is the reason you cannot get a reference to it via dijit.byId("numberOfDateNode"). Use dojo.byId("numberOfDateNode") instead and you are all set.
dojoAttachPoint or its HTML5 valid version data-dojo-attach-point is being used inside a dijit template to attach a reference to DOM node or child dijit to dijit javascript object, which is the reason dijit.byId('alarmCatDialog').numberOfDateNode has a reference to your <input type='input' class='dateWidgetInput' .../>.
The main reason to use data-dojo-attach-point is that:
you can create multiple instances of dijit and therefore your template cannot identify nodes/dijits by IDs as you will have multiple nodes/dijits with the same ID
it's an elegant declarative way, so your code won't be full of dijit.byId/dojo.byId.
It is important to keep track of what is the contents and which is the template of the dijit.Dialog. Once you set contents of a dialog, its markup is parsed - but not in a manner, such that the TemplatedMixin is applied to the content-markup-declared-widgets.
To successfully implement a template, you would need something similar to the following code, note that I've commented where attachPoints kicks in.
This SitePen blog renders nice info on the subject
define(
[
"dojo/declare",
"dojo/_base/lang",
"dijit/_Templated",
"dijit/_Widget",
"dijit/Dialog"
], function(
declare,
lang,
_Templated,
_Widget,
Dialog
) {
return declare("my.Dialog", [Dialog, _Templated], {
// set any widget (Dialog construct) default parameters here
toggle: 'standard',
// render the dijit over a specific template
// you should be aware, that once this templateString is overloaded,
// then the one within Dialog is not rendered
templateString: '<div bgColor="#FFFFFF" bgOpacity="0.4">' +// our domNode reference
'<div class="dijitInline">' +
// setting a dojoAttachPoint makes it referencable from within widget by this attribute's value
' <input type="input" class="dateWidgetInput" dojoAttachPoint="numberOfDateNode" selected="true">' +
'</div>' +
'</div>',
constructor: function(args, srcNodeRef) {
args = args || {} // assert, we must mixin minimum an empty object
lang.mixin(this, args);
},
postCreate: function() {
// with most overrides, preferred way is to call super functionality first
this.inherited(arguments);
// here we can manipulate the contents of our widget,
// template parser _has run from this point forward
var input = this.numberOfDateNode;
// say we want to perform something on the numberOfDateNode, do so
},
// say we want to use dojo.Stateful pattern such that a call like
// myDialogInstance.set("dateValue", 1234)
// will automatically set the input.value, do as follows
_setDateValueAttr: function(val) {
// NB: USING dojoAttachPoint REFERENCE
this.numberOfDateNode.value = val;
},
// and in turn we must set up the getter
_getDateValueAttr: function() {
// NB: USING dojoAttachPoint REFERENCE
return this.numberOfDateNode.value;
}
});
});