I'm working on a project at the moment using angular JS.
I've used a directive to switch from advanced search so that the results can be viewed on its own page. basically when submit is clicked, the advanced search is hidden and only results table can be seen. so now, once on results table, I want to be able to go back to that advanced search to the point before I hit that submit button, the data is still there, I have just reversed the directive in a way. any suggestions would be greatly appreciated, this is all fairly new to me.
thanks! (please note, my search controller uses TypeScript)
this is being called just under the submit button on the search_partial.html
<div class="submit">
<button class="btn btn-primary" type="button" name="Submit" ng-click="vm.validateForm()" ng-disabled="!(!!vm.hospitalNumberInput || !!vm.nhsNumberInput || !!vm.fullNameInput || !!vm.sexInput || vm.yearOfBirthInput || !!vm.streetInput || !!vm.cityInput
|| !!vm.postCodeInput || !!vm.chosenCountry)">Search</button>
Clear all
</div>
</form>
<section>
<div id="searchDirective" search-results patients="vm.results" class="ng-hide"></div>
</section>
and I have a directives file called search.results.directive.js
(function () {
angular
.module('app.search.results')
.directive('searchResults', function() {
return {
restrict: 'AE',
templateUrl: 'app/search/Partials/result_partial.html',
scope: {
patients: '='
}
};
});
})();
so what I'm trying to do now that I can see the results-partial.html on the screen in front of me, I want to be able to click a back button on there to take me back to the search-partial.html at the point before the user clicked that submit button so that the data in the boxes can be altered if needs be or more search data added. (at the moment I have a back href going to the home url, it works for now, but that's what im hoping to replace).
results-partial.html:
<main class="container">
<!-- RESULT -->
<section class="result-display">
<form>
<div class="searchresults content table-responsive">
<h2>Search Criteria: </h2>
<h2> Search Results: {{patients.length}} patients found</h2>
<table class="table resultstable table-striped">
<thead>
<tr class="theading">
<th>Hospital number</th>
<th>NHS Number</th>
<th>Full Name</th>
<th>DOB</th>
<th>Sex</th>
</tr>
</thead>
<!--repeated simply for style insight-->
<tbody>
<tr ng-repeat="patient in patients">
<td>{{patient.resource.hospitalNumber}}</td>
<td>{{patient.resource.nhsNumber}}</td>
<td>{{patient.resource.nameString}}</td>
<td>{{patient.resource.birthDate}}</td>
<td>{{patient.resource.gender.toUpperCase()}}</td>
</tr>
</tbody>
</table>
</div>
<a href style="float: right; font-size:120%;" onclick="location.href='http://localhost:3000/';"><i class="close"></i><u>Back to Search</u></a>
</form>
</section>
</main>
If I understand the question right, you want to preserve the values in the input.
You can use a factory or value to store the data.
myApp.factory('DataHolder', function (){
return data;
});
// Or, with value
myApp.value('DataHolder', data);
And in your controller you can access that data anywhere.
myApp.controller('Ctrl', function ($scope, DataHolder){
$scope.data = DataHolder;
});
So when you come back to the back state, if you have data stored you can get it back to show it.
fixed it. managed to get it working my changing the flag to false with "returnToSearch()" function at the bottom.
createDisplayParams(): void {
// add in search params to display params
var paramTypes: string[] = [];
for (var i: number = 0; i < this.searchParams.length; ++i) {
var objectIndex: number = paramTypes.indexOf(this.searchParams[i].ParamName);
if (objectIndex === -1) {
// if param name dosen't exist, add it to the paramTypes
paramTypes.push(this.searchParams[i].ParamName);
}
}
for (var j: number = 0; j < paramTypes.length; ++j) {
var valueParams: core.ISearchParam[] = [];
valueParams =_.filter(this.searchParams, searchParam => { //lodash
return searchParam.ParamName == paramTypes[j];
});
var valueStrings: string[] = [];
valueParams.forEach(v => valueStrings.push(v.ParamValue));
this.displayParams.push({ paramType: paramTypes[j], paramValue: valueStrings.join(", ") });
}
}
obtainPatientInformation(): void {
this.createSearchParams();
if (this.searchParams.length > 0) {
var rawResults: angular.IPromise<core.IPatient> = this.searchDataService.performAdvancedSearch(this.searchParams);
var searchControllerInstance: SearchController = this;
this.createDisplayParams();
rawResults.then(
function success(response: any): void {
if (response.data.entry && response.data.entry.length > 0) {
searchControllerInstance.noResults = false;
searchControllerInstance.results = response.data.entry;
for (var index: number = 0; index < searchControllerInstance.results.length; index++) {
var patient: core.IEntry = searchControllerInstance.results[index];
patient.resource.nameString = '';
if (patient.resource.name) {
var familyNameArray: string[] = patient.resource.name[0].family;
for (var familyIndex: number = 0; familyIndex < familyNameArray.length; familyIndex++) {
var familyName: string = familyNameArray[familyIndex];
patient.resource.nameString = patient.resource.nameString + ' ' + familyName.toUpperCase() + ',';
}
var givenNameArray: string[] = patient.resource.name[0].given;
for (var givenIndex: number = 0; givenIndex < givenNameArray.length; givenIndex++) {
var givenName: string = givenNameArray[givenIndex];
patient.resource.nameString = patient.resource.nameString + ' ' + givenName;
}
}
var identifiers: core.IIdentifier[] = patient.resource.identifier;
for (var indentifierIndex: number = 0; indentifierIndex < identifiers.length; indentifierIndex++) {
var identifier: core.IIdentifier = identifiers[indentifierIndex];
if (identifier.system) {
if (identifier.system === 'nhsNumber') {
patient.resource.nhsNumber = identifier.value;
}
if (identifier.system === 'hospitalNumber') {
patient.resource.hospitalNumber = identifier.value;
}
}
}
}
} else {
searchControllerInstance.noResults = true;
searchControllerInstance.results = null;
}
});
}
this.searchClicked = true;
this.checkSearch();
}
checkSearch(): void {
var resultSectionElements: angular.IAugmentedJQuery = angular.element('[id*="resultSection"]');
var advanceSearchSectionElements: angular.IAugmentedJQuery = angular.element('[id*="advanceSearchSection"]');
if (this.searchClicked) {
resultSectionElements.removeClass('ng-hide');
advanceSearchSectionElements.removeClass('ng-show');
advanceSearchSectionElements.addClass('ng-hide');
} else {
resultSectionElements.addClass('ng-hide');
advanceSearchSectionElements.removeClass('ng-hide');
advanceSearchSectionElements.addClass('ng-show');
}
}
returnToSearch(): void {
this.searchClicked = false;
this.searchParams.splice(0,this.searchParams.length);
this.displayParams.splice(0,this.displayParams.length);
this.checkSearch();
}
Related
I am trying to add an item from a string to insert into a table along with the other information. I have followed a tutorial for a shopping cart and I am in need of adding the total cost to the record. I have the item in the array and have added what I believe to be the items I need. What I am having an issue with is implementing it in the controller side of the project. Below is the code I have, I am not 100% sure if what I added for the total price is correct. This should be in decimal form. thank for your help.
Shopping Cart CSHTML page. This is not the whole page just relevant parts.
using (Html.BeginForm("AddOrder", "Parts", new { id = "f" }))
{
<table id="tableOrder" class="table table-hover">
<tr>
<th>Part Number</th>
<th>Unit Price</th>
<th>Qty Selected</th>
<th>Description</th>
<th>Total Price</th>
</tr>
#foreach (var parts in Model)
{
<tr>
<td>#parts.Material</td>
<td>#string.Format("{0:C2}", parts.SellingPrice)</td>
<td>#parts.QtySelected</td>
<td>#parts.Description</td>
<td>#string.Format("{0:C2}", (parts.SellingPrice * parts.QtySelected))</td>
</tr>
totalOrder += (parts.QtySelected * parts.SellingPrice);
#Html.HiddenFor(p => parts.Material)
#Html.HiddenFor(p => parts.QtySelected)
}
</table>
<!-- TOTAL PRICE-->
<h4 style="margin-left: 66%;">Total : <span class="label label-info">#string.Format("{0:C2}", totalOrder)</span></h4>
#Html.HiddenFor(p => totalOrder)
<div class="modal-footer">
<button type="button" class="btn btn-secondary" id="close" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" id="SaveOrder" data-toggle="modal" data-target="#additionalInfo">Save Order</button>
</div> <!-- MODAL FOOTER-->
}
Java Script portion.
$("#SaveOrder").click(function () {
var $form = $(this).closest('form');
var dataPart = $form.serializeArray();
console.log(dataPart);
var arrIdPart = [];
var arrQtyPart = [];
var totalPrice = [];
for (i = 0; i < dataPart.length; i++)
{
if (dataPart[i].name == 'parts.Material')
{
arrIdPart.push(dataPart[i].value);
}
else if (dataPart[i].name == 'parts.QtySelected')
{
arrQtyPart.push(dataPart[i].value);
}
else if (dataPart[i].name == 'totalOrder')
{
totalPrice.push(dataPart[i].value);
}
}
$.ajax({
type: 'POST',
url: '#Url.Action("AddOrder", "Parts")',
data: { arrIdPart, arrQtyPart },
success: function (response) {
if(response.data == true)
{
alert("Order has saved successfully ");
}
else
{
alert("Order did not save successfully ! ");
}
},
error: function (error) {
alert("Order did not collect data successfully ! ");
}
});
});
Here is the controller action. I have added the parts to all of these that have to do with totalPrice. The issue is how to implement it in the record add to customer.
[HttpPost]
public ActionResult AddOrder(string[] arrIdPart, int[] arrQtyPart, decimal[] totalPrice)
{
int countPart = arrIdPart.Length;
int CompanyId = (int)Session["CompanyId"];
bool statusTran = false;
EDIT - added
decimal totPrice = totalPrice.Length;
CustomerEntities _context = new CustomerEntities();
using (DbContextTransaction dbTran = _context.Database.BeginTransaction())
{
try
{
CompanyNames customer = _context.CompanyNames.Find(CompanyId);
if (customer != null)
{
EDIT - Changed this
customer.Ordered.Add(new Orders { OrderDate = DateTime.Now, TotalPrice = totPrice });
}
Orders orderSelected = customer.Ordered.LastOrDefault();
if (orderSelected != null)
{
for (int i = 0; i < countPart; i++)
{
Parts selectedPart = _context.Parts.Find(arrIdPart[i]);
orderSelected.OrderDetail.Add(new OrderDetails { Parts = selectedPart, Quantity = arrQtyPart[i] });
}
}
//Save Changes
int countResult = _context.SaveChanges();
//Commit Transaction
dbTran.Commit();
if (countPart > 0)
{
statusTran = true;
partsList.Clear();
}
}
catch (Exception)
{
dbTran.Rollback();
}
}
return Json(new { data = statusTran }, JsonRequestBehavior.AllowGet);
}
}
However I am not getting anything for totalOrder in the script. Says its null. But in my 'console.log(dataPart);' In the console it is there with the name totalOrder.
Not saying it's the final answer but I can't put multiline code in a comment..
I wish to point out that you don't post the total price you calculated, to the server:
type: 'POST',
url: '#Url.Action("AddOrder", "Parts")',
data: { arrIdPart, arrQtyPart }, //look, no totalprice data? You did all those efforts to calc it and then did nothing with it?
success: function (response) {
if(response.data == true)
totalPrice should probably be called arrSubtotalPart by the way, for consistency..
Warning: The server receives the items and the quantities, it should work the price out from that rather than let the end user dictate how much he wants to pay for an order by manipulating the JavaScript
I'm using ngInfiniteScroll in a few different places to show contacts, and missed calls. It loops over every item and adds a ng-click to show user profile. The scrolling works fine in all locations until you actually click on a user/call. Afterwards the scroll never triggers again in either contacts nor phone calls. I've looked at their docs and seen infinite-scroll-listen-for-event which I figured is what I needed for infinite scroll to reset after the click event, but it doesn't appear to be working. I can't tell if I have the $emit in the wrong location, or what?
HTML
<md-list infinite-scroll="recent.moreContacts()" infinite-scroll-disabled="recent.busy" infinite-scroll-listen-for-event="resetInfiniteScrollList" infinite-scroll-distance="1" infinite-scroll-immediate-check="false" infinite-scroll-parent="true">
<md-list-item ng-repeat="client in recent.clients | orderBy:'firstName'" ng-click="recent.viewCustomer(client.id)" class="repeater-list-item recent-session" layout="row" layout-align="start start" aria-label="View {{client.fullName}}'s profile">
<div ng-if="client.avatar" class="md-avatar" style="background-image: url('{{client.avatar}}');"></div>
<div ng-if="!client.avatar" class="md-avatar" ></div>
<div class="md-list-item-text">
<h3>{{client.firstName}} {{client.lastName}} <span ng-if="!client.firstName">Unknown <small class="text-tertiary text-gray">(Customer: {{client.id}})</small></span></h3>
</div>
</md-list-item>
</md-list>
loading contacts
vm.moreContacts = function () {
$timeout(function () {
$rootScope.closeSidenavs();
$rootScope.btnActive = 'contacts';
$mdSidenav('contacts').open();
$sessionStorage.currentTab = 'contacts';
if (vm.busy || vm.foundAllContacts || vm.contactsSearchActive) {
} else {
vm.busy = true;
api.get('/account/' + $rootScope.user.account.id + '/clients?page=' + vm.contactsNextPage, function (success, data) {
if (success) {
for (var i = 0; i < data.clients.length; i++) {
vm.clients.push(data.clients[i]);
}
self.totalFound = data.totalFound;
self.lastPageLoaded = data.page;
if (data.clients.length === 25) {
vm.contactsNextPage = vm.contactsNextPage += 1;
console.log(vm.contactsNextPage);
}
if (vm.clients.length === self.totalFound) {
vm.foundAllContacts = true;
}
} else {
vm.isClientsError = true;
}
vm.busy = false;
});
}
}, 10);
};
ng-click function
vm.viewCustomer = function (clientId) {
if (clientId > 0) {
if ($mdMedia('xs') || $mdMedia('sm')) {
$rootScope.btnActive = '';
$rootScope.closeSidenavs();
}
$location.path(
"/customer/" + clientId + "/feed"
);
$rootScope.$emit('resetInfiniteScrollList');
//vm.contactsSearchActive = false;
}
};
I am connecting to the Yahoo weather service API and made a little simple weather app using Angular. I also created a F - C temperature converter that triggers with the help of ng-change(). However for some reason this only works once on initialization.
For some reason I can not make sense why ng-repeat would only fire once inside an ng-repeat. Please see code below. Any help would be appreciated.
***I should mentioned that when I placed a "debugger" inside my function called, changedTemperatureTo, it triggers the "debugger" when I convert from F->C, but the "debugger" doesn't even trigger from C->F, the second time round. By second time around, I mean after I flipped the radio button from F->C the first time. When I flip it back, nothing happens - Debugger doesn't trigger.
VIEW:
{{date}}
<span ng-repeat="temp in temperatureNames">
<input type="radio" name="selectedTemperatureNamed" ng-model="selectedTemperatureName" ng-value="temp" ng-change="changedTemperatureTo(temp)"/> {{temp}}
</span>
<select ng-model="sort">
<option value="cityNameForForecast(td)">City</option>
<option value="high">High</option>
<option value="low">Low</option>
</select>
<input type="checkbox" ng-model="reverse"/> <small>*Check to Reverse Order</small>
<div ><br>
<table class="tg">
<thead>
<tr >
<th class="tg-031e"></th>
<th class="tg-031e"></th>
<th class="tg-031e"></th>
<th class="tg-031e">High</th>
<th class="tg-031e">Low</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="td in forecastAll | orderBy:sort:reverse">
<th class="tg-031e">{{cityNameForForecast(td)}}</th>
<th class="tg-031e"><img src="http://l.yimg.com/a/i/us/we/52/{{ td.code }}.gif"></th>
<th class="tg-031e">{{td.text}}</th>
<th class="tg-031e">{{td.high}}</th>
<th class="tg-031e">{{td.low}}</th>
</tr>
</tbody>
</table>
</div>
CONTROLLER:
/*global angular */
var weatherControllers = (function () {
var weatherControllers = angular.module('weatherControllers', []);
// Declare the application controller and inject the scope reference.
weatherControllers.controller('AppCtrl', ['$scope', function ($scope) {
// Define the title model.
$scope.title = "AngularJS Tutorial - Yahoo Weather App";
}]);
// Inject the scope and new weatherService reference into the controller.
weatherControllers.controller('ListCtrl', ['$scope', 'weatherService', function ($scope, weatherService) {
// Define the forecast data.
}]);
// Inject the scope and new weatherService reference into the controller.
weatherControllers.controller('WeatherCtrl', ['$scope', 'weatherService',
function ($scope, weatherService) {
// Define the forecast data.
// forcastOne >
weatherService.getWeather('Vancouver').success(function (data) {
$scope.forecastVan = weatherService.getForecastFromData(data);
console.log("forecastVan");
console.log($scope.forecastVan);
// console.log($scope.forecastVan[0]);
// console.log("$scope.forecastVan[0]['date']");
// console.log($scope.forecastVan[0]['date']);
$scope.forecastDate = $scope.forecastVan[0]['date'];
weatherService.getWeather('Honolulu').success(function (data) {
$scope.forecastHon = weatherService.getForecastFromData(data);
console.log("forecastHon");
console.log($scope.forecastHon);
console.log($scope.forecastHon[0]);
weatherService.getWeather('San Diego').success(function (data) {
$scope.forecastSan = weatherService.getForecastFromData(data);
console.log("forecastSan");
console.log($scope.forecastSan);
console.log($scope.forecastSan[0]);
weatherService.getWeather('Havana Cuba').success(function (data) {
$scope.forecastHav = weatherService.getForecastFromData(data);
console.log("forecastHav");
console.log($scope.forecastHav);
console.log($scope.forecastHav[0]);
// Create index model
$scope.forecastAll = [$scope.forecastVan[0], $scope.forecastHon[0], $scope.forecastSan[0], $scope.forecastHav[0]]
});
});
});
});
$scope.cityNameForForecast = function (forecast) {
if ($scope.forecastVan[0] == forecast) {
return 'Vancouver';
}
else if ($scope.forecastHon[0] == forecast) {
return 'Honolulu';
}
else if ($scope.forecastSan[0] == forecast) {
return 'San Diego';
}
else if ($scope.forecastHav[0] == forecast) {
return 'Havana Cuba';
}
};
// Temperature
$scope.temperatureNames = ['C', 'F'];
$scope.selectedTemperatureName = $scope.temperatureNames[1];
$scope.changedTemperatureTo = function (temperatureName) {
// debugger;
if (temperatureName == 'C') {
$scope.forecastAll = weatherService.arrayToCelsius($scope.forecastAll);
}
else if (temperatureName == 'F') {
$scope.forecastAll;
}
};
}]);
// Inject scope, $routeParams, and cardService
weatherControllers.controller('DetailCtrl', ['$scope', '$routeParams', 'weatherService',
function ($scope, $routeParams, weatherService) {
weatherService.getWeather($scope, $routeParams.cityID);
$scope.cityName = $routeParams.cityName;
weatherService.getWeather($routeParams.cityName).success(function (data) {
$scope.forecast = weatherService.getForecastFromData(data);
});
$scope.temperatureNames = ['C', 'F'];
$scope.selectedTemperatureName = $scope.temperatureNames[1];
}]);
return weatherControllers;
}());
SERVICES:
weatherApp.factory("weatherService", function ($http) {
'use strict';
return {
doSomething: function ($scope) {
},
getWeather: function (city) {
var url = this.getUrlForCity(city);
return $http.get(url);
},
getUrlForCity: function (city) {
// Weather codes:
var weatherCodes = {'Vancouver': 'CAXX0518', 'Honolulu': 'USHI0026', 'San Diego': 'USCA0982', 'Havana Cuba': 'CUXX0003'}
var city = weatherCodes[city] // Now on can call all cities at once
var yahooAPI = "'http://weather.yahooapis.com/forecastrss?p=";
var format = "'&format=json&diagnostics=true&callback=";
var yql = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20rss%20where%20url%3D";
var url = yql + yahooAPI+ city + format;
return url;
},
getForecastFromData: function (data) {
try {
var stringified = JSON.stringify(data); // Convert to a string.
stringified = stringified.split("\\n").join(""); // Remove new line '/n'.
var listing = JSON.parse(stringified); // Convert to object.
var forecast = []; // Store 5 day forecast.
var forecastDate = []; // Stores forecast date
for (var result in listing) {
for (var item in listing[result].results) {
for (var day in listing[result].results.item.forecast) {
forecast.push(listing[result].results.item.forecast[day]);
}
}
}
}
catch (error) {
alert("Weather reading error:" + error.name + ": "
+ error.message);
}
return forecast;
},
arrayToCelsius: function (forecastArray) {
for (var i = 0; i < forecastArray.length; i++) {
forecastArray[i]['high'] = this.getCelsius(forecastArray[i]['high']);
forecastArray[i]['low'] = this.getCelsius(forecastArray[i]['low']);
}
return forecastArray;
},
getCelsius: function (fahrenheit) {
var fTempVal = this.getForecastFromData(fahrenheit);
// debugger;
// $scope.celsius = this.getForecastFromData;
var celsius = ((fahrenheit - 32) * 0.56).toFixed(0);
return celsius; // Calculation goes here.
}
}
});
From what I can see, you initially set the temperature to be in Fahrenheit.
// Temperature
$scope.temperatureNames = ['C', 'F'];
$scope.selectedTemperatureName = $scope.temperatureNames[1];
The issue happens here:
$scope.changedTemperatureTo = function(temperatureName) {
// debugger;
if (temperatureName == 'C') {
$scope.forecastAll = weatherService.arrayToCelsius($scope.forecastAll);
} else if (temperatureName == 'F') {
/*
You aren't doing anything to the forcastAll variable when the temperature
is F
*/
$scope.forecastAll;
}
};
Nothing is happening when the temperatureName == 'F'. So it'll convert from Farenheight to Celcius, but then nothing happens when going back.
Hope this helps!
We have a situation as mentioned below:
There is a set of data for a search panel, it's called in several pages with different types of components and placement of it. There can be combo boxes, radio buttons, input boxes and buttons.
Knockout has a feature of template binding in which we can have the flexibility to show numerous panels on condition using a template in the html mapped to MOdel.
Below is the code and pattern:
HTML:
<div id="content-wrapper">
<div class="spacer"></div>
<div>
<table class="data-table">
<thead>
<tr>
<th colspan="4"> Search </th>
</tr>
</thead>
<tbody data-bind="foreach: preSearchData" >
<tr>
<!-- ko template: { name: 'label_' + templateName()} -->
<!-- /ko -->
</tr>
</tbody>
</table>
</div>
</div>
<script type="text/html" id="label_Combo">
<td>It is a Combo </td>
</script>
<script type="text/html" id="label_Number">
<td>
It is a Number
</td>
</script>
MODEL:
Models.Components = function(data) {
var self = this;
self.number = data.number;
self.labelCd = data.labelCd;
self.xmlTag = data.xmlTag;
self.Type = new Cobalt.Models.Type(data.Type);
};
Models.Type = function(data) {
var self = this;
self.component = data.component;
self.records = data.records;
self.minLength = data.minLength;
self.maxLength = data.maxLength;
self.defaultValue = data.defaultValue;
self.targetAction = data.targetAction;
};
Models.ComponentType = function (paymentTypeCode, data, actionId) {
var ret;
self.templateName(data.component);
if (!data || (actionId === Cobalt.Constant.Dashboard.copyProfile))
data = {};
if (paymentTypeCode == Cobalt.Constant.Dashboard.creditCard)
ret = new Cobalt.Models.CreditCardPaymentType(data.cardHolderName, data.cardNumber, data.cardExpireDate);
else if (paymentTypeCode == Cobalt.Constant.Dashboard.dd)
ret = new Cobalt.Models.DDPaymentType(data.pinNumber);
else if (Cobalt.Utilities.startsWith(paymentTypeCode, Cobalt.Constant.Dashboard.yahooWallet)) {
if (!data && paymentTypeCode.indexOf('~') > -1) {
data.payCode = paymentTypeCode.substr(paymentTypeCode.indexOf('~') + 1, paymentTypeCode.lastIndexOf('~'));
data.billingAgentId = paymentTypeCode.substr(paymentTypeCode.lastIndexOf('~') + 1);
}
ret = new Cobalt.Models.WalletPaymentType(data.payCode, data.billingAgentId);
}
else if (paymentTypeCode == Cobalt.Constant.Dashboard.ajl) {
ret = new Cobalt.Models.DDPaymentType(data.pinNumber);
}
else
ret = data || {};
return ret;
};
Models.POCModel = function () {
var self = this;
self.templateName = ko.observable();
self.preSearchData = ko.observableArray([]);
self.getResultData = function () {
var data = Cobalt.Data.getResultData();
var componentList = data.componentList;
self.preSearchData(componentList);
};
};
Above code gives me a error saying:
Ajax error: parsererror ( Error: Unable to parse bindings. Message: ReferenceError: templateName is not defined; Bindings value: template:
{ name: 'label_' + templateName()} ) cobalt.init.js:66
This is not a direct answer to your question, but it shows an alternate way of doing this using the ViewModel type to find the view (Template)
http://jsfiddle.net/nmLsL/2
Each type of editor is a ViewModel
MyApp.Editors.BoolViewModel = function(data) {
this.checked = data;
};
MyApp.Editors.BoolViewModel.can = function(data) {
return typeof data === "boolean";
};
And it has a can function that determins if it can edit the value
I then usea library called Knockout.BindingConventions to find the template connected to the ViewModel
https://github.com/AndersMalmgren/Knockout.BindingConventions/wiki/Template-convention
Your foreach binding creates a child binding context, which doesn't include templateName since that's part of the parent. Replace it with
<!-- ko template: { name: 'label_' + $parent.templateName()} -->
In the following code, whenever you delete an item from the delete link in the list, it will only delete the item from the list, but it will not delete the currently selected item. (The item displaying once you click on it). However, if you click on the delete link next to the currently selected item, it will delete from both places.
To replicate what I'm seeing:
Add a bunch of items by typing in the text box and hitting enter a few times.
Select one of the items from the list.
Click delete next to the item when it displays below.
This is the correct behavior.
Select another item you created earlier.
Now click the delete link next to the item in the list.
The item is removed from the list, but not the currently displayed item.
When I step into the code $scope.currentUser is undefined when I click on the delete link in the list.
Why is this happening?
<html ng-app="myApp">
<head>
<script src="http://code.angularjs.org/1.0.1/angular-1.0.1.min.js"></script>
<script>
var app = angular.module('myApp', []);
app.config(function($routeProvider) {
$routeProvider.when('/User/:id', {
controller: UserCtrl,
template: '<h1>{{currentUser.name}}</h1> <a ng-click="deleteUser(currentUser.id)">delete me</a>'
});
});
app.factory('userSvc', function(){
return new UserService();
});
function UserCtrl($scope, $routeParams, $location, userSvc) {
var currUser = userSvc.getUser($routeParams.id);
$scope.currentUser = currUser;
$scope.users = userSvc.getAllUsers();
$scope.addUser = function () {
var user = {
id: userSvc.nextId(),
name: $scope.addUserName
};
userSvc.addUser(user);
$scope.addUserName = '';
$location.url('/User/' + user.id);
};
$scope.deleteUser = function(id) {
if($scope.currentUser != null && $scope.currentUser.id == id) {
$scope.currentUser = null;
}
userSvc.delete(id);
};
};
function UserService() {
var users = [{id: 1, name: 'Ben' }];
this.delete = function(id) {
for(var i = 0; i < users.length; i++) {
var user = users[i];
if(user.id == id) {
users.splice(i,1);
}
}
};
this.addUser = function(user) {
users.push(user);
};
this.getAllUsers = function() {
return users;
};
this.getUser = function(id) {
for(var i = 0; i < users.length; i++) {
var user = users[i];
if(user.id == id) {
return user;
}
}
};
this.nextId = function() {
var maxId = 0;
for(var i = 0; i < users.length; i++) {
var user = users[i];
maxId = Math.max(maxId, user.id);
};
return maxId + 1;
};
}
</script>
</head>
<body>
<div ng-controller="UserCtrl">
<form ng-submit="addUser()">
<input ng-model="addUserName" type="text"/>
<input type="submit" value="Add"/>
</form>
<ul>
<li ng-repeat="user in users">{{user.name}} <a ng-click="deleteUser(user.id)">delete</a></li>
</ul>
</div>
<div ng-view></div>
</body>
</html>
It turns out that selecting a user from the list actually also created a brand new scope that was seperate from the one used to bind the list.
Thanks to Gloopy's comment above to check out Batarang, I was able to see this happen. If this happens to help you, please +1 his comment.
According to the documentation on Scopes some directives will actually cause a new scope to be created. I'm assuming that clicking a link that is being handled by the $routeProvider also results in the creation of a whole new scope tree, likely because it's creating another instance of that controllor.