I am trying to display characters from different languages on my screen. These characters are generated by a csv file which is convert to JSON format as follows
{
"id": 32,
"name": "Hindi",
"csv": [
{
"keycode": "1",
"unicode": "\u0D15",
"chakra": "1"
},
{
"keycode": "1",
"unicode": "\u0D15",
"chakra": "1"
},
{
"keycode": "1",
"unicode": "\u0D15",
"chakra": "1"
}
]
}
I am seeing the html unicodes displayed on the screen though I am using $sce.trustAshtml() for the unicode values via filter. Here is my angularJS code.
controller :
app.controller("KeyboardController", [
"$scope", "Restangular", "LanguageModel", "KeyboardModel", "$sce", function($scope, Restangular, LanguageModel, KeyboardModel, $sce) {
var languageResource;
$scope.languages = LanguageModel.getAll();
languageResource = Restangular.one("languages");
angular.element("#chakra").css("display", "none");
languageResource.getList("all").then(function(languageobject) {
LanguageModel.addAll(languageobject);
KeyboardModel.addlanguage(languageobject);
$scope.onscreen = KeyboardModel.getallkeys();
$scope.firstmaintablekeys = KeyboardModel.maintablelayout1();
});
}
]);
keyboardModel : service.
app.factory("KeyboardModel", function() {
var KeyboardModel;
KeyboardModel = function() {
this.keys = [];
this.key = [];
this.keyid = {};
this.languageobject = {};
};
KeyboardModel.prototype = {
addlanguage: function(languageobject) {
this.languageobject = languageobject;
},
getallkeys: function() {
var currentlanguage, div, grouped, i, mod, totalrows;
currentlanguage = this.languageobject[1];
totalrows = currentlanguage.csv.length;
grouped = [];
i = 0;
while (i < totalrows) {
div = Math.floor(i / 5);
mod = i % 5;
if (mod === 0) {
grouped[div] = [];
}
grouped[div][mod] = currentlanguage.csv[i];
i++;
}
this.keys = grouped;
return grouped;
},
maintablelayout1: function(language) {
var i, table;
i = 0;
table = [];
while (i < 4) {
table[i] = this.keys[i];
i++;
}
return table;
}
};
return new KeyboardModel();
});
HTML :
<div class="maintable1 frame1" ng-show="frame1">
<table>
<thead></thead>
<tbody>
<tr ng-repeat="data in firstmaintablekeys">
<td ng-repeat="row in data" data-keycode="{{ row.keycode }}" data-chakra="{{ row.chakra }}" ng-mousedown="displaychakra(row.keycode, row.unicode, $event)" ng-mouseup="hidechakra()" ng-click="sharetext(row.unicode)">
<span ng-bind-html="row.unicode | unsafeFilter"></span>
</td>
</tr>
</tbody>
</table>
</div>
Filter :
app.filter("unsafeFilter", function($sce) {
return function(val) {
return $sce.trustAsHtml(val);
};
});
Am I missing something? Why do I get unicodes displayed instead of their corresponding values?
EDIT : I have been told its a server side issue. Here is my controller which reads the CSV file that contains the Unicodes.
class LanguagesController < ApplicationController
def index
end
def all
availablelanguages = {
:data => []
}
#language = Language.all.each do |eachlanguage|
availablelanguages[:data] << {
:id => eachlanguage.id,
:name => eachlanguage.languagename,
:csv => []
}
CSV.foreach(eachlanguage.path) do |row|
availablelanguages[:data].each do |single|
single[:csv] << {
:keycode => row[0],
:unicode => row[1],
:chakra => row[2]
}
end
end
#data = JSON.pretty_generate(availablelanguages[:data])
end
render json: #data
end
end
Here is the screenshot of the JSON response generated. It adds an additional backlash to make the string literal. http://i.imgur.com/FY0F1l9.png?1
I had to do the same recently. JSON returned unicode (Chinese). Didn't have to do any thing to decode it. Just insert this line in your header area.
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
Related
i'm trying to add product filtering functionality like this: filter product image and after add filter i have to clear filter as user wish like this one: clear filter image if anyone give me real world idea with some more details or short word it can help me be more proffessional.
Well let's assume your filters data is like this:
[
{
catrgory: "Color",
values: [
"Silver",
"Black",
...
]
},
{
catrgory: "Material",
values: [
"Acrylic",
"Rayon",
...
]
},
...
]
You should have 2 states in your component. One for holding the filters data and another for holding the selected filters.
Fetch your filters data from the server once. (Or use a local file).
Each time the user selects a filter, you should add it to your selected filters data.
Each time the user remove a filter, you should remove it from your selected filters data.
Hope it helps (It's just a guide not the whole solution):
const MyComponent = () => {
const [filtersData, setFiltersData] = useState([]);
const [selectedFilters, setSelectedFilters] = useState([]);
useEffect(() => {
// fetch data from the server
}, []);
const handleSelectFilter = (category, value) => {
const newSelectedFilters = [...selectedFilters];
let filter = newSelectedFilters.find((selectedFilter) => selectedFilter.category === category);
if(filter) {
filter.values.push(value);
} else {
filter = {
catrgoty: category,
values: [value]
}
newSelectedFilters.push(filter);
}
setSelectedFilters(newSelectedFilters);
}
const handleDeleteFilter = (category, value) => {
let newSelectedFilters = [...selectedFilters];
const index = newSelectedFilters.findIndex((selectedFilter) => selectedFilter.category === category);
newSelectedFilters = newSelectedFilters.splice(index, 1);
setSelectedFilters(newSelectedFilters);
}
return (
<div>
{
filtersData.map((filterItem, index) => {
return (
<div key={index}>
<div>{filterItem.category}</div>
{
filterItem.values.map((value) => {
return (
<div key={value} onClick={() => handleSelectFilter(filterItem.category, value)}>{value}</div>
)
})
}
</div>
)
})
}
{
selectedFilters.map((selectedFilter, index) => {
return (
<div key={index}>
<div>{selectedFilter.category}</div>
{
selectedFilter.values.map((value) => {
return (
<div key={value} onClick={() => handleDeleteFilter(filterItem.category, value)}>{value}</div>
)
})
}
</div>
)
})
}
</div>
);
}
I really think I'm going crazy here. So I made a shopping-type app, add to cart and etc.
I have extra comments on each Item which the user can enter any text they want to. The state is correct on "onChangeText" of the input, I checked it with the console. However, when I want to save it (after an edit of the cart), despite the console.log's making sense and that showing the correct state etc, the options changes successfully, but the comments does not. This is very weird as all the other cart array object do change, except the comment. Here is the code:
saveItemCart() {
var index = this.state.cartItems.indexOf(x => x.date === this.state.dateAdded);
let cartItemsArray = this.state.cartItems;
temp = { 'catNumber': this.state.catNumber, 'itemNumber': this.state.itemNumber, 'quantity': this.state.itemQuantity, 'options': this.state.selectedOptions, 'date': this.state.dateAdded, 'comments': this.state.commentsText};
cartItemsArray[index] = temp;
this.setState({ cartItems: cartItemsArray }, () => {
this.updateTotal();
this.setState({ selectedOptions: [], checked: [] })
})
}
State:
state = {
ModalItemShown: false,
ModalCartShown: false,
ModalEditShown: false,
isShowToast: false,
isShowToastError: false,
rest_id: this.props.route.params['restaurantid'],
menuData: this.getMenu(),
catNumber: 1,
itemNumber: 1,
dateAdded: null,
commentsText: "",
cartItems: [],
checked: [],
selectedOptions: [],
total: 0,
itemQuantity: 1,
}
Input (inside the render):
<View style={styles.modalOptions}>
<Input placeholder="..." placeholderTextColor="gray" defaultValue={this.state.commentsText} onChangeText={text => this.setState({ commentsText: text }, () => {console.log(this.state.commentsText)})} />
</View>
<Button shadowless style={styles.button1} color="warning" onPress={() => {
let my = this;
this.showToast(true);
setTimeout(function () { my.showToast(false) }, 1000);
this.saveItemCart();
this.hideModalEdit(false);
}}
>Save</Button>
The problem is in the input of the EDIT cart modal(i.e. page). If the user puts the comment initially before adding it to his cart, then when he opens the edit modal it has the correct comment. If I change it in the edit and click save, and check again, it does not work.
updateTotal:
updateTotal() {
var cartArrayLen = this.state.cartItems.length;
var i;
var j;
var total = 0;
var cart = this.state.cartItems;
for (i = 0; i < cartArrayLen; i++) {
var catNum = cart[i]["catNumber"];
var itemNum = cart[i]["itemNumber"];
var q = cart[i]["quantity"];
var itemPrice = this.state.menuData[catNum - 1][catNum.toString()]["itemsarray"][itemNum]["price"];
itemPrice = Number(itemPrice.replace(/[^0-9.-]+/g, ""));
total = total + (itemPrice * q);
var allItemOptions = this.state.menuData[catNum - 1][catNum.toString()]["itemsarray"][itemNum].options;
var k;
for (k = 0; k < cart[i].options.length; k++) {
var title = cart[i].options[k]["title"];
var index_onmenu = allItemOptions.findIndex(x => x.title === title);
var option_price;
if (Array.isArray(cart[i].options[k].indexes)) {
for (j = 0; j < cart[i].options[k].indexes.length; j++) {
var price_index = cart[i].options[k].indexes[j];
option_price = allItemOptions[index_onmenu].price[price_index]
total = total + Number(option_price) * q
}
} else {
j = cart[i].options[k].indexes
option_price = allItemOptions[index_onmenu].price[j]
total = total + Number(option_price) * q
}
}
};
console.log("New Total: " + total);
this.setState({ total: total }, () => {
this.setState({ itemQuantity: 1 })
})
}
I don't see where you defined the temp variable, but assuming that it is defined somewhere, I think the problem is in how you are updating the cartItems array. Let me explain it by adding some comments in your code:
saveItemCart() {
var index = this.state.cartItems.indexOf(x => x.date === this.state.dateAdded);
let cartItemsArray = this.state.cartItems; // --> Here you are just copying the array reference from the state
temp = { 'catNumber': this.state.catNumber, 'itemNumber': this.state.itemNumber, 'quantity': this.state.itemQuantity, 'options': this.state.selectedOptions, 'date': this.state.dateAdded, 'comments': this.state.commentsText};
cartItemsArray[index] = temp;
this.setState({ cartItems: cartItemsArray }, () => { // --> then you just updated the content of the array keeping the same reference
this.updateTotal();
this.setState({ selectedOptions: [], checked: [] })
})
}
Try doing creating a new array, so the react shallow comparison algorithm can track the state change, like this:
this.setState({ cartItems: Array.from(cartItemsArray) }, /* your callback */);
or
this.setState({ cartItems: [...cartItemsArray]}, /* your callback */);
Hope it helps!
I'm struggling with passing the csv strings via ViewBag in the correct format.
I know the result should be like ["Blue","Brown","Green"] but my script is generated as [Blue,Brown,Green] instead.
And then I get the Uncaught ReferenceError : Blue is not defined.
How can I format it in my controller to pass in the correct way?
This is my code in the controller
public ActionResult Index()
{
List<string> teamsList = new List<string>();
List<string> salesCount = new List<string>();
foreach (var team in Db.Teams)
{
teamsList.Add(team.Name);
int count = Db.LeadCampaigns.Count(i => Db.Agents.FirstOrDefault(a => a.AgentId == i.AgentId).TeamId == team.TeamId && i.LeadStatusId == Db.LeadStatuses.FirstOrDefault(s => s.Name == "SALE").LeadStatusId);
salesCount.Add(count.ToString());
}
ViewBag.SaleCount_List = string.Join(",", salesCount);
ViewBag.TeamName_List = string.Join(",", teamsList);
return View();
}
And here is my script in the view.
<script>
var barChartData =
{
labels: [#Html.Raw(ViewBag.TeamName_List)],
datasets: [{
label: 'TeamWise Sales Count',
backgroundColor: [
"#f990a7",
"#aad2ed",
"#9966FF",
"#99e5e5",
"#f7bd83",
],
borderWidth: 2,
data: [#ViewBag.SaleCount_List]
}]
};
window.onload = function () {
var ctx1 = document.getElementById("barcanvas").getContext("2d");
window.myBar = new Chart(ctx1,
{
type: 'bar',
data: barChartData,
options:
{
title:
{
display: true,
text: "TeamWise Sales Count"
},
responsive: true,
maintainAspectRatio: true
}
});
}
Your plugin expects an array of values, but your passing it a string by using String.Join().
Pass the array using
ViewBag.SaleCount_List = salesCount;
ViewBag.TeamName_List = teamsList;
(or better pass a view model with 2 IEnumerable<string> properties) and then convert it to a jacascript array
var saleCounts = #Html.Raw(Json.Encode(ViewBag.SaleCount_List))
var teamNames = #Html.Raw(Json.Encode(ViewBag.TeamName_List))
var barChartData =
{
labels: teamNames,
datasets: [{
....
],
borderWidth: 2,
data: saleCounts
}]
};
Using your current syntax:
const string quote = "\"";
foreach (var team in Db.Teams)
{
teamsList.Add(quote + team.Name + quote);
int count = Db.LeadCampaigns.Count(i => Db.Agents.FirstOrDefault(a => a.AgentId == i.AgentId).TeamId == team.TeamId && i.LeadStatusId == Db.LeadStatuses.FirstOrDefault(s => s.Name == "SALE").LeadStatusId);
salesCount.Add(count.ToString());
}
I am currently working on an Ionic mobile application which will eventually take photos, attach a location and send them inside a post request to a rails endpoint. After looking at this link and this link and countless others, I have been unable to find any solid information on implementing this particular feature.
I can upload photos through the browser using a html input form, which is then added to the database and is displayed on the app via a get request.
However at the moment when taking a photo on the phone and attempting to send it via a post request directly from the app, only the location information is being received, the image is not being correctly encoded.
Here is the jSON data that has been received, its returning "image_url":"/images/main/missing.png".
{ "id":6,"city":"Greater London",
"country":"United Kingdom","created_at":"2015-05-14T21:22:22.825Z",
"updated_at":"2015-05-14T21:22:22.825Z","image_file_name":null,
"image_content_type":null,"image_file_size":null,
"image_updated_at":null,"image_url":"/images/main/missing.png" }
Here is the code:
Angular factory making post request:
.factory('Posts', function($http) {
var o = { posts: [] };
o.getAll = function() {
return $http.get('http://localhost:8100/posts').success(function(data) {
angular.copy(data, o.posts);
});
};
o.addPost = function(post) {
return $http.post('https://shielded-hamlet-4665.herokuapp.com/posts', post);
};
return o;
})
Angular Controller taking photo:
.controller("CameraCtrl", function($scope, $cordovaCamera, $http, Posts) {
var id = 0;
var options = {
quality : 75,
destinationType : Camera.DestinationType.FILE_URI,
sourceType : 1,
allowEdit : true,
encodingType: 0,
targetWidth: 380,
targetHeight: 450,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false
};
function getLocCoords(position) {
$scope.lat = position.coords.latitude;
$scope.lon = position.coords.longitude;
$http.get('http://maps.googleapis.com/maps/api/geocode/json?latlng=' + $scope.lat +',' + $scope.lon + '&sensor=true')
.success(function(data) {
var home = data.results[0].address_components;
for (var i = 0; i < home.length; i++) {
if(home[i].types.indexOf("administrative_area_level_2") > -1) {
$scope.city = home[i].long_name;
break;
};
};
for (var i = 0; i < home.length; i++) {
if(home[i].types.indexOf('country') > -1) {
$scope.country = home[i].long_name;
break;
};
};
})
};
$scope.takePicture = function() {
navigator.geolocation.getCurrentPosition(getLocCoords);
$cordovaCamera.getPicture(options).then(function(imageData) {
$scope.imgURI = imageData;
id ++;
var post = { id: id, country: $scope.country, city: $scope.city, image: $scope.imgURI, likes: 0, comments: [] }
Posts.addPost(post);
}, function(err) {
});
}
Post Controller from the Rails Database:
class PostsController < ApplicationController
skip_before_filter :verify_authenticity_token
def index
#posts = Post.all
render json: #posts, :callback => params['callback'], :content_type => 'application/javascript', :methods => [:image_url]
end
def new
#post = Post.new
end
def create
Post.create(post_params)
redirect_to '/posts'
end
def post_params
params.require(:post).permit(:city, :country, :image)
end
end
I have not done a great deal of work with the ionic framework so please forgive my ignorance. Any help would be greatly appreciated.
Managed to solve this using the cordovaFileTransfer.upload method.
The rails end point was also filtering params and looking for a post object, with a image string, and only an image string was being provided.
The following code is now working
Angular factory making post request:
.factory('Posts', function($http, $cordovaFileTransfer) {
var o = { posts: [] };
o.getAll = function() {
return $http.get('https://shielded-hamlet-4665.herokuapp.com/posts').success(function(data) {
angular.copy(data, o.posts);
});
};
o.addPost = function(post) {
var options = {
fileKey: "image",
fileName: "image.jpeg",
chunkedMode: false,
mimeType: "image/jpeg",
params: { city: post.city, country: post.country, lat: post.lat, lon: post.lon }
};
$cordovaFileTransfer.upload('http://shielded-hamlet-4665.herokuapp.com/posts', post.image, options)
.then(function(result){
console.log("Code = ok");
}, function(error){
console.log("Code = " + error);
}, function(progress){});
};
return o;
})
Angular Controller taking photo:
.controller("CameraCtrl", function($scope, $cordovaCamera, $http, Posts) {
post = {};
var options = {
quality : 75,
destinationType : Camera.DestinationType.FILE_URI,
sourceType : 1,
allowEdit : true,
encodingType: 0,
targetWidth: 380,
targetHeight: 450,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false
};
function getLocCoords(position) {
post.lat = position.coords.latitude;
post.lon = position.coords.longitude;
$http.get('http://maps.googleapis.com/maps/api/geocode/json?latlng=' + post.lat +',' + post.lon + '&sensor=true')
.success(function(data) {
var home = data.results[0].address_components;
for (var i = 0; i < home.length; i++) {
if(home[i].types.indexOf("administrative_area_level_2") > -1) {
post.city = home[i].long_name;
break;
};
};
for (var i = 0; i < home.length; i++) {
if(home[i].types.indexOf('country') > -1) {
post.country = home[i].long_name;
break;
};
};
})
};
$scope.takePicture = function() {
navigator.geolocation.getCurrentPosition(getLocCoords);
$cordovaCamera.getPicture(options).then(function(imageData) {
post.image = imageData;
Posts.addPost(post);
}, function(err) {});
};
});
Post controller from rails database:
class PostsController < ApplicationController
skip_before_filter :verify_authenticity_token
def index
#posts = Post.all
render json: #posts, :callback => params['callback'], :content_type => 'application/javascript', :methods => [:image_url]
end
def new
#post = Post.new
end
def create
Post.create(post_params)
redirect_to '/posts'
end
def post_params
params.permit(:city, :country, :image, :lat, :lon)
end
end
i am having issues with paging on server side with datatables jquery plugin. The paging control at the bottom of the grid shows
Showing 1 to 10 of 10 entries (filtered from 7,253 total entries)
but am not filtering any records. If I click the next or previous links no ajax requests are being sent back to the server. I would expect to see
Showing 1 to 10 of 7253 entries.
Controller Code
public ActionResult GetDataTable(DataTableParamModel param)
{
var allhotelscount = db.Businesses.OfType<Hotel>().Count();
var filteredhotels = db.Businesses.OfType<Hotel>().OrderBy(h => h.Name);
IEnumerable<DataTableHotel> displayedhotels = from c in filteredhotels
.Skip(param.iDisplayStart).Take(param.iDisplayLength)
select new DataTableHotel
{
Id = c.Id,
Name = c.Name,
CityState = c.PhysicalCity + ", " + c.PhysicalState,
PhoneNumber = c.PhoneNumber,
PrimaryContact = c.PrimaryContact.FirstName + " " + c.PrimaryContact.LastName,
PrimaryContactPhone = c.PrimaryContact.OfficePhone,
PrimaryContactEmail = c.PrimaryContact.EmailAddress,
};
return Json(new
{
sEcho = param.sEcho,
iTotalRecords = allhotelscount,
iTotalDisplayRecords = displayedhotels.Count(),
aaData = displayedhotels
},
JsonRequestBehavior.AllowGet);
}
View Code:
<table id="myDataTable" class="display">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>City, State</th>
<th>Phone</th>
<th>Contact</th>
<th>Phone</th>
<th>Email</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script type="text/javascript">
$(document).ready(function () {
$('#myDataTable').dataTable({
"bServerSide": true,
"sAjaxSource": "/Hotel/GetDataTable",
"bProcessing": true,
"aoColumns": [
{ "mData": "Id" },
{ "mData": "Name" },
{ "mData": "CityState" },
{ "mData": "PhoneNumber" },
{ "mData": "PrimaryContact" },
{ "mData": "PrimaryContactPhone" },
{ "mData": "PrimaryContactEmail" },
]
});
});
You passed a wrong value to iTotalDisplayRecords, see below code:
return Json(new
{
sEcho = param.sEcho,
iTotalRecords = allhotelscount,
iTotalDisplayRecords = allhotelscount,
aaData = displayedhotels
},
JsonRequestBehavior.AllowGet);