Having a binding issue with a child object of an ember.view object. Code is as follows:
--Textbox class extended from Ember.TextField
App.TextBox = Ember.TextField.extend({
attributeBindings:['placeholder', 'autocorrect','autocapitalize'],
value:null,
isInvalid:true,
validate:function(){
this.set('isInvalid', false);
return false;
},
focusOut:function(event){
this.validate();
}});
---View that uses App.Textbox
App.ViewTextBox = Ember.View.extend({
name:"viewName",
label:"View Label",
input: App.TextBox.extend({
placeholder:function(){
return this.get('parentView').get('label');
}.property('label').cacheable()
})});
--Handlebars with bindings
{{#view App.ViewTextBox}}
{{label}}<br/>
{{#view input valueBinding="parentView.value"}}
<div {{bindAttr class="isInvalid"}}></div>
{{/view}}{{/view}}
Issue is this:
1) After the initial rendering of the view, the class is properly set, but subsequent changes to the isInvalid value, through the onFocusOut call, do not change the class in the DOM. Ideas?
You can't use a view block helper with Ember.TextField.
Related
Below is the sample code where I am trying to pass/sync the value between the two controllers. For the same in view I have a textbox and two place holders for showing the value of the textbox.
I have somehow achieved the behavior but still could not figure out why the code is not working in one place and doing well in another. I have mentioned 2 ways, one is working(second way) and one is not(first way).
I have used following:
1 service
2 controllers
1 view
Service
mcApp.factory('mcService', function($rootScope){
var service = {};
//variable 1
service.message = 'Default';
//function 1
service.getMessage = function(){
return this.message;
}
//function 2
service.setMessage = function(msg){
this.message = msg;
}
return service;
});
Controller - First way - Not working
mcApp.controller('mcController1', function ($scope, mcService) {
$scope.message = mcService.getMessage();
$scope.setmsg = function(msg){
mcService.setMessage(msg);
}
});
mcApp.controller('mcController2', function($scope, mcService){
$scope.message = mcService.getMessage();
});
View - First way - Not working
<div ng-app="mcApp">
<div ng-controller="mcController1">
<input type="text" ng-model="message" ng-change="setmsg(message)">
<p ng-bind="message"></p>
</div>
<div ng-controller="mcController2">
<p ng-bind="message"></p>
</div>
</div>
In above code I am updating the value of scope variable "message" by calling the service method "getMessage()" in "mcController2". However it is not getting updated in the view.
Below is the code where instead of directly using the service method "getMessage()" in "mcController2" I have assigned the service to the scope variable.
Controller - Second way - Working
mcApp.controller('mcController1', function ($scope, mcService) {
$scope.message = mcService.getMessage();
$scope.setmsg = function (msg) {
mcService.setMessage(msg);
}
});
mcApp.controller('mcController2', function ($scope, mcService) {
$scope.service = mcService;
});
View - Second way - Working
<div ng-app="mcApp">
<div ng-controller="mcController1">
<input type="text" ng-model="message" ng-change="setmsg(message)">
<p ng-bind="message"></p>
</div>
<div ng-controller="mcController2">
<p ng-bind="service.message"></p>
</div>
</div>
Please NOTE : Using the $rootScope.$broadcast in service and $scope.$on in controller in First way also gets the work done. But I am not able to figure out why Fisrt way is not working.
the first way not work because you pass the primitive object --- pass by value
-- pass by value if the old value has change the variable will not be reflect.
the second way worked well because you pass the complex object --- pass by reference .
-- pass by reference if the old value has change the variable will be reflect.
ex :
var x = {
name: "BeSaRa",
country: "Egypt",
like: [
'PHP',
'Javascript',
'MYSQL'
]
};
var v = x.name; // pass by value becouse the string is primitve object
var r = x.like; // pass by reference because the array is Complex Object
// try to change the name below this line
x.name = "Ahmed Mostafa";
console.log(v) // output --> "BeSaRa" it is not reflected by the change
// try to change the like property below this line
x.like.push("AngularJS"); // add AngularJS to the Array
console.log(r) // output ['PHP','Javascript','MYSQL','AngularJS'];
i hope you understand now :D
the primitives types in JavaScript:
Boolean
Null
Undefined
Number
String
Symbol (new in ECMAScript 6)
any thing else Complex :)
I am sure this has been asked before but alas I can't find it - any help to point me in the right direction would be greatly appreciated.
I am loading a view / view model with Durandal and during the Activate method I am calling for a single record to be fetched and then displayed. I am getting the record back (checked the XHR response and all data comes back ok) but I can only assume that the view is loading before the data is ready to display. No JS errors, no errors at all for that matter, but just a big whitespace in the middle of my screen, even where I know data should show...
ViewModel :
define(['durandal/system', 'services/logger', 'services/datacontext'], function (system, logger, datacontext) {
var aForm = ko.observable();
var initialized = false;
function activate(routeData) {
var id = parseInt(routeData.id);
return refresh(id);
};
function refresh(id) {
return datacontext.getaFormById(id, aForm);
}
var vm = {
activate: activate,
aForm: aForm,
title: "THE TITLE DISPLAYS JUST FINE"
}
return vm;
});
View :
<h3 class="page-title" data-bind="text: title"></h3>
<div class="container-fluid" data-bind="with: aForm">
<div class="row-fluid">
<div class="span12">
<strong>Testing</strong>
<strong data-bind="text: id"></strong>
</div>
</div>
<h2 data-bind="text: description"></h2>
<h2 data-bind="text: checkType().description"></h2>
</div>
I threw in the Testing strong and it doesn't even render, only the title does. Can anyone point me in the right direction? I would create a fiddle but it works when I hardcode the data in the ViewModel.
EDIT :
Ok after digging into it a bit more it is possible I am not returning the object properly, specifically in the data.entity return type. Would this cause the issue?
var getaFormById = function (aFormId, aFormObservable) {
var query = EntityQuery.from('aForms')
.where('id', '==', aFormId);
return manager.executeQuery(query)
.then(querySucceeded)
.fail(queryFailed);
function querySucceeded(data) {
if (aObservable) {
aObservable(data.entity);
}
logger.log('Retrieved selected [aForm] from remote data source', data, system.getModuleId(datacontext), true);
}
}
You are not correctly filling your observable in your executeQuery success callback that is why your UI is not rendered correctly.
From the executeQuery documenation the successFunction called with the following argument
successFunction([data])
data Object
results Array of Entity
...
So you need to fill your observable from the data.results array and not form data.entity (which just returns undefined):
if (aObservable) {
aObservable(data.results[0]);
}
You can tell Durandal to hold off binding by returning a jQuery promise() from the activate function.
See this video by Ryan Keeter for the explanation: http://www.youtube.com/watch?v=w_XjWg6xL8I
I'm wondering if this is the right way of passing a JavaScript callback function to a partial view. So depending on the view I'm on the partial view may do different things. So I pass in a JavaScript call back function to achieve that.
Here is a generic function to call my partial view and where I pass in the JavaScript call back function.
function showAjaxMessage(targetDiv, ajaxMessage) {
var ajaxLoader = "<img src='Content/loader.gif' alt=''>";
$(targetDiv).html("<p>" + ajaxLoader + " " + ajaxMessage+"</p>");
}
function getPartialView(actionUrl, targetDiv, ajaxMessage, cbFunc) {
showAjaxMessage(targetDiv, ajaxMessage);
$.get(actionUrl, { callback: eval(cbFunc).toString()}, function(result) {
$(targetDiv).html(result);
});
}
Here is an example of me calling it:
getPartialView("Home/OpenLogin", "#divLogon", "Loading...", function() { alert('This is the call back function!'); test(); });
Here is the controller where I get the callback function and save it to a model. Then I pass it back to the partial view.
// returns a login dialog which will be injected
// into a placeholder div on the client
public ActionResult OpenLogin(string callback)
{
var baseModel = new BaseModel();
baseModel.cbFunc = callback;
return PartialView("LoginDialog", baseModel);
}
Here is an example of my partial view. Where you can see I get the call back function and set in the init function.
#model MvcApplication8.Models.BaseModel
function init(cb){
if(cb!=undefined){
cb();
}
else{
alert("undefined");
}
}
function test(){
alert("Testing my call back");
}
$(function () {
init(#Html.Raw(#Model.cbFunc));
});
The solution above works, but the main question that comes to mind is this the right way of doing it? Passing the call back function from the controller to the partial view sounds wrong, but how else would you do it? Any ideas?
Based on your example, I do not understand why would pass the callback function to a partial view. The partial view is rendered inside a div on the same page. Why not just declare the function on the page so that it's available to the rendered partial view?
I try to filter out unnecessary properties by casting object to some interface. Next, I serialize it to JSON object like the following code.
#{
var program = ViewBag.Program as IProgram;
}
<script type="text/javascript">
window.program = #Html.Raw(Json.Encode(program));
</script>
However, It still serialize all properties in original object instead of serialize only properties that are defined in interface.
How to serialize only properties in current object type instead of serialize all properties that are in original object?
Use a view model of course:
#{
var program = new
{
Foo = ViewBag.Program.Property1,
Bar = ViewBag.Program.Property2
};
}
<script type="text/javascript">
window.program = #Html.Raw(Json.Encode(program));
</script>
and by the way this is something that should be done inside your controller action, not clutter your view. So instead of passing this object inside ViewBag.Program directly pass a view model that will contain only the properties you need to be serialized.
public ActionResult SomeAction()
{
Program program = ...
ViewBag.Program = new
{
Foo = ViewBag.Program.Property1,
Bar = ViewBag.Program.Property2
};
return View();
}
Oh, and use a real view model and cut that ViewBag out.
I have a Dropdownlistfor connected to my model. When the page is loaded the model is empty, but I have a button on the page that updates the model. My problem is that my dropdownlist doesn't update.
Markup:
#Html.DropDownList("ddlRaces", new SelectList(ViewBag.Races, "RaceId", "Name"))
<input type="button" id="btnChangeRace" class="btnGo" value=" " />
#Html.DropDownListFor(m => m.Timers, new SelectList(Model.Timers, "TimerId", "StartTime"), "Velg timer:")
Script:
btnChangeRace.click(function () {
url = "/TimeMerger/GetTimers/?raceId=" + ddlRaces.val();
$.get(url);
});
Codebehind:
[HttpGet]
public ActionResult GetTimers(int raceId)
{
var timeMergeModel = new TimeMergerModel();
timeMergeModel.Timers = TimerModel.GetTimers(raceId);
return View(timeMergeModel);
}
$.get(url);
Here you are sending an AJAX request but you are doing nothing in the success callback so nothing will update. There is not even a success callback. So you need to define a success callback:
$.get(url, function(result) {
// result here will represent the value returned by the server
// which in your case is HTML. So here you might need to update
// the relevant portion of your page.
});
Also your DropDownListFor definition is wrong. You are using the same model variable as first and second argument (Model.Timers). The first first argument of this helper should be a scalar property to which you are binding and not a list. It should be:
#Html.DropDownListFor(
m => m.SelectedTimerValue,
new SelectList(Model.Timers, "TimerId", "StartTime"),
"Velg timer:"
)
where SelectedTimerValue would be a property on your view model that will hold the selected value. Also why you are using DropDownList instead of DropDownListFor for the first drop down? The whole idea of a view model is that it will contain all the necessary information so that the view would simply display it.