I have a list in my Xamarin Forms app that I have being bound to data. This all works and I know I am getting data because if I tap on the screen the list shows the data, but I assume the list should show each item without having to tap on the screen.
Here is my xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="PDInstall.Views.LayoutsPage"
Title="Layouts">
<ContentPage.Content>
<StackLayout>
<ListView x:Name="layoutsList" IsPullToRefreshEnabled="True"
Refreshing="layoutsList_Refreshing" ItemTapped="layoutsList_ItemTappedAsync">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Name}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
And here is my code behind:
public LayoutsPage (Job job)
{
InitializeComponent ();
_job = job;
Task.Run(() => GetLayoutsListAsync());
}
private async Task GetLayoutsListAsync()
{
if(CrossConnectivity.Current.IsConnected)
{
layoutsList.IsRefreshing = true;
IList<CloudBlockBlob> layouts = await azureFileUpload.ListJobBlobsAsync(_job.JobId);
IList<CloudEditableBlob> layoutList = new List<CloudEditableBlob>();
foreach(var item in layouts)
{
CloudEditableBlob editableBlob = new CloudEditableBlob();
editableBlob.Name = item.Name.Replace(_job.JobId.ToString() + ": ", "");
editableBlob.Container = item.Container;
editableBlob.Parent = item.Parent;
editableBlob.StorageUri = item.StorageUri;
editableBlob.Uri = item.Uri;
layoutList.Add(editableBlob);
}
layoutsList.IsRefreshing = false;
await Task.Run(() => layoutsList.ItemsSource = layoutList);
}
else
{
await DisplayAlert("No Internet Connection", "Please Reconnect to the Internet and re-open PDInstall", "OK");
}
layoutsList.EndRefresh();
}
I am getting a list of blobs from azure, they are just PDFs that we have stored. I get the list of blobs then I have to put it into a custom class, so I can change the name, then I put that into the list. This all works fine up until it tries to show the list and I get a blank page until I tap it where it then shows the list.
Does anyone know if I can programmatically do a tap or something to get that list to show? Or possibly another way to get the data show without having to tap on the screen?
Thanks in advance!
Replace
await Task.Run(() => layoutsList.ItemsSource = layoutList);
With
Device.BeginInvokeOnMainThread(() =>{ layoutsList.ItemsSource = layoutList; });
Related
I am trying to show/echo users location on a webpage using maxmind geoip2 paid plan, I also want to show different images based on the state/city names output.
For example, if my webpage shows the user is from New York, I would like to show a simple picture of New York, if the script detects the user is from Washington, the image should load for Washington.
This is the snippet I have tried but doesn't work.
<script type="text/javascript">
if
$('span#region=("New York")') {
// Display your image for New York
document.write("<img src='./images/NY.jpg'>");
}
else {
document.write("<img src='./images/different.jpg'>");
}
</script>
This is the code in the header.
<script src="https://js.maxmind.com/js/apis/geoip2/v2.1/geoip2.js" type="text/javascript"></script>
<script>
var onSuccess = function(geoipResponse) {
var cityElement = document.getElementById('city');
if (cityElement) {
cityElement.textContent = geoipResponse.city.names.en || 'Unknown city';
}
var countryElement = document.getElementById('country');
if (countryElement) {
countryElement.textContent = geoipResponse.country.names.en || 'Unknown country';
}
var regionElement = document.getElementById('region');
if (regionElement) {
regionElement.textContent = geoipResponse.most_specific_subdivision.names.en || 'Unknown region';
}
};
var onError = function(error) {
window.console.log("something went wrong: " + error.error)
};
var onLoad = function() {
geoip2.city(onSuccess, onError);
};
// Run the lookup when the document is loaded and parsed. You could
// also use something like $(document).ready(onLoad) if you use jQuery.
document.addEventListener('DOMContentLoaded', onLoad);
</script>
And this simple span shows the state name in body text of the Html when the page loads.
<span id="region"></span>
now the only issue is the image doesn't change based on users location, what am i doing wrong here?
Your example is missing some code, but it looks like you are running some code immediately and some code in a callback, a better way to do it is to have all the code in the callback:
// whitelist of valid image names
var validImages = ["NJ", "NY"];
// get the main image you want to replace
var mainImage = document.getElementById('mainImage');
if (mainImage) {
// ensure there is a subdivision detected, or load the default
if(geoipResponse.subdivisions[0].iso_code && validImages.includes( && geoipResponse.subdivisions[0].iso_code)){
mainImage.src = "./images/" + geoipResponse.subdivisions[0].iso_code + ".jpg";
} else {
mainImage.src = "./images/different.jpg";
}
}
Then just have the image you want to replace be:
<img src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" id="mainImage" />
Notes:
If you are using a responsive image, make sure your transparent gif is the same ratio height of to width as your final image to avoid page reflows.
You will have to load the different.jpg in the onError callback as well.
In grails, I am trying to get a list of checked check boxes.
I have the list of check boxes, but my issues are two:
1) when I click on a single item in the list and click submit - I only get the value "on". If I click more than one check box item, I get something like this:
[Ljava.lang.String;#5a37f9f7
2). I do not get a list or the name of the item checked.
Here is my code for the check boxes in the gsp:
<g:form action="submitForm">
<ul class="columns3">
<g:each in="${name}" var="fileName" >
<g:checkBox value="${false}" name="${ 'fileName'}" /> ${fileName.replaceFirst(~/\.[^\.]+$/, '')}<br>
</g:each>
</ul>
<br>
<br>
<g:submitButton name="Submit"/>
</g:form>
and here is the controller code (groovy):
class Read_dirController {
def index() {
def list = []
def dir = new File("/home/ironmantis/Documents/business/test_files")
dir.eachFileRecurse (FileType.FILES) { file ->
list << file
}
list.each {
println it.name.replaceFirst(~/\.[^\.]+$/, '')
}
render(view: "index", model: [name:list.name])
params.list('fileName')
}
def displayForm() { }
def submitForm(String fileName) {
render fileName
//render(view: "tests_checked", fileName)
}
}
I tried to bind an id to the check boxes, but I keep getting an exception error.
Any help you can give I truly appreciate it; I am new to grails.
ironmantis7x
You can use the beautiful command object for this. For this ,first make a class RequestCO having the boolean fields.
class RequestCO {
boolean isChecked;
String name;
}
And
class RequestParentCO {
List<RequestCO> requestCOs = [].withLazyDefault { new RequestCO() }
}
Now you just simply bind all your request to RequestParentCO in your action:
def submitForm(RequestParentCO parentCO) {
println parentCO.requestCOs.findAll { it.isChecked }
}
This will give you all the checked checkboxes results.
GSP
<g:form action="process">
<ul class="columns3">
<g:each in="${["one", "two", "three"]}" var="fileName" status="i">
<g:hiddenField name="requestCOs[${i}].name" value="${fileName}"/>
<g:checkBox name="requestCOs[${i}].isChecked"/> ${fileName}<br>
</g:each>
</ul>
<g:submitButton name="Submit"/>
This way,
def submitForm() {
def values = request.getParameterValues("fileName")
//here values contains string array which are selected in checkbox
}
you can use request.getParameterValues("fileName") method, this will give selected checkbox in string array
I'm trying to write a simple unit test and can't seem to figure it out. I want to test a bootstrap modal to ensure it displays the correct contents when I pass certain object properties to it. Here's what my modal code looks like:
import React, { Component, PropTypes } from 'react';
import { Button, Modal } from 'react-bootstrap';
class ModalBox extends Component {
render() {
const { modalBox } = this.props;
let content;
if (modalBox.contentBody) {
content = modalBox.contentBody;
} else {
content = (
<span>
<Modal.Header closeButton onHide={this.close.bind(this)}>
<Modal.Title>{modalBox.title}</Modal.Title>
</Modal.Header>
<Modal.Body>
{modalBox.message}
</Modal.Body>
{modalBox.isConfirm &&
<Modal.Footer>
<Button onClick={modalBox.onCancel} className="modal-button cancel">{modalBox.cancelText || 'Cancel'}</Button>
<Button onClick={modalBox.onConfirm} className="modal-button confirm">{modalBox.confirmText || 'Confirm'}</Button>
</Modal.Footer>
}
</span>
);
}
return (
<Modal show={typeof modalBox != 'undefined'} onHide={this.close.bind(this)} dialogClassName={modalBox.dialogClassName || ''} backdrop={modalBox.backdrop || true}>
{content}
</Modal>
);
}
}
So for a test, I want to make sure that if I pass the prop modalBox containing the contentBody field that it just returns the contentBody for the modal body. Here's an example of what I'm trying to test:
it("renders only contentBody when provided", () => {
let modalBoxObj = {
contentBody: <div className="test-content-body">This is a test.</div>
};
let element = React.createElement(ModalBox, {modalBox: modalBoxObj});
let component = TestUtils.renderIntoDocument(element);
let modalWrapper = TestUtils.scryRenderedDOMComponentsWithClass(component, 'modal');
// modalWrapper returns an empty array, so this returns "Expected 0 to be 1"
expect(modalWrapper.length).toBe(1);
let testBody = TestUtils.scryRenderedDOMComponentsWithClass(component, 'test-content-body');
// testBody returns an empty array, so this returns "Expected 0 to be 1"
expect(testBody.length).toBe(1);
// this returns "TypeError: 'undefined' is not an object (evaluating 'testBody[0].innerHTML')"
expect(testBody[0].innerHTML).toEqual("This is a test.");
}
I've also tried doing shallow rendering with TestUtils.createRenderer and trying that approach, but had no luck with it. Based on the examples I've seen online and previous testing experience with react <0.14, I feel this test should work. I just don't know what I'm missing or misunderstanding. In the past, I did something like below and just looked at the componentNode object to find elements and such, but componentNode is returning null.
let component = TestUtils.renderIntoDocument(element);
let componentNode = findDOMNode(component);
Thanks for your help!
The solution ended up being to add a ref to the ModalBox component. Once added, we were able to target the node like this:
let component = TestUtils.renderIntoDocument(<ModalBox modalBox={modalBoxObj} />);
let componentNode = findDOMNode(component.refs.modalBox._modal);
I'm using Sitecore 8 and the new Email Experience Manager module.
I have configured a newsletter email message with an empty list from the listmanager as recipients.
When subscribing for the newsletter via a selfmade form, I receive an email address and a name.
Now I want to make a new contact with this mail and name and add it to the list in my listmanager via code.
Is there any way to call this list via the api and add a contact to it?
To create a contact, you can use the sample code below, the contact name is usually the domain name plus the username, e.g. domain\username.
public static Contact CreateContact([NotNull] string contactName, [NotNull] string contactEmail, [NotNull] string contactLanguage)
{
Assert.ArgumentNotNullOrEmpty(contactName, "contactName");
Assert.ArgumentNotNullOrEmpty(contactEmail, "contactEmail");
Assert.ArgumentNotNullOrEmpty(contactLanguage, "contactLanguage");
var contactRepository = new ContactRepository();
var contact = contactRepository.LoadContactReadOnly(contactName);
if (contact != null)
{
return contact;
}
contact = contactRepository.CreateContact(ID.NewID);
contact.Identifiers.AuthenticationLevel = AuthenticationLevel.None;
contact.System.Classification = 0;
contact.ContactSaveMode = ContactSaveMode.AlwaysSave;
contact.Identifiers.Identifier = contactName;
contact.System.OverrideClassification = 0;
contact.System.Value = 0;
contact.System.VisitCount = 0;
var contactPreferences = contact.GetFacet<IContactPreferences>("Preferences");
contactPreferences.Language = contactLanguage;
var contactEmailAddresses = contact.GetFacet<IContactEmailAddresses>("Emails");
contactEmailAddresses.Entries.Create("test").SmtpAddress = contactEmail;
contactEmailAddresses.Preferred = "test";
var contactPersonalInfo = contact.GetFacet<IContactPersonalInfo>("Personal");
contactPersonalInfo.FirstName = contactName;
contactPersonalInfo.Surname = "recipient";
contactRepository.SaveContact(contact, new ContactSaveOptions(true, null));
return contact;
}
After creating the contact, use the following sample code to add the contact to a recipient list.
var repository = new ListManagerCollectionRepository();
var recipientList = repository.GetEditableRecipientCollection(recipientListId);
if (recipientList != null)
{
var xdbContact = new XdbContactId(contactId);
if (!recipientList.Contains(xdbContact, true).Value)
{
recipientList.AddRecipient(xdbContact);
}
}
Essentially you can follow this example
<%# Page Language="c#" %>
<%# Import Namespace="Sitecore.Analytics" %>
<%# Import Namespace="Testing.ContactFacets.Model" %>
<!DOCTYPE html>
<html>
<head>
<title>Add Employee Data</title>
</head>
<body>
<%
var contact = Tracker.Current.Contact;
var data = contact.GetFacet<IEmployeeData>("Employee Data");
data.EmployeeId = "ABC123";
%>
<p>Employee data contact facet updated.</p>
<p>Contact ID: <b><%=contact.ContactId.ToString()%></b></p>
<p>Employee #: <b><%=data.EmployeeId%></b></p>
</body>
</html>
The changes are then written when the session is abandoned, like so
<%# Page language="c#" %>
<script runat="server">
void Page_Load(object sender, System.EventArgs e) {
Session.Abandon();
}
</script>
<!DOCTYPE html>
<html>
<head>
<title>Session Abandon</title>
</head>
<body>
</body>
</html>
Follow this link for the source and more information - http://www.sitecore.net/learn/blogs/technical-blogs/getting-to-know-sitecore/posts/2014/09/introducing-contact-facets
I have had the exact same issue, i.e. the list manager reports 0 contacts after adding the contact to the recipient list.
I have investigated the issue closer and found that adding a contact to a recipient list actually just sets a field on the contact in the "sitecore_analytics_index" index (assuming you use Mongo/XDB as the underlying storage). Specifically, Sitecore should update the "contact.tags" field on the contact document with the value "ContactLists:{recipientListGuid}". I tried opening the index with Luke to verify that this field was indeed not being set in the index. The index is located in C:\inetpub\wwwroot[Sitename]\Data\indexes\sitecore_analytics_index.
This led me to the conclusion, that you have to save the contact after adding him to the recipient list.
Summing up, the following code works for me:
var ecm = EcmFactory.GetDefaultFactory();
XdbContactId contactId = /* some valid contact id */;
LeaseOwner leaseOwner = new LeaseOwner("UpdateContact-" + Guid.NewGuid().ToString(), LeaseOwnerType.OutOfRequestWorker);
Sitecore.Analytics.Tracking.Contact contact;
string webClusterName;
var status = ecm.Gateways.AnalyticsGateway.TryGetContactForUpdate(contactId.Value,
leaseOwner,
TimeSpan.FromSeconds(5),
TimeSpan.FromSeconds(5),
out contact, out webClusterName);
var recipientList = ecm.Bl.RecipientCollectionRepository.GetEditableRecipientCollection(recipientListId);
if (recipientList != null)
{
if (!recipientList.Contains(contactId, true).Value)
{
recipientList.AddRecipient(contactId);
}
}
contact.ContactSaveMode = ContactSaveMode.AlwaysSave;
var contactRepository = new ContactRepository();
var success = contactRepository.SaveContact(contact, new ContactSaveOptions(true, leaseOwner));
Note, the above code is used in an update-scenario. In your case, I guess you just have to move this code:
contactRepository.SaveContact(contact, new ContactSaveOptions(true, null));
After this:
var recipientList = EcmFactory.GetDefaultFactory().Bl.RecipientCollectionRepository.GetEditableRecipientCollection(recipientListId);
if (recipientList != null)
{
var xdbContact = new XdbContactId(contactId);
if (!recipientList.Contains(xdbContact, true).Value)
{
recipientList.AddRecipient(xdbContact);
}
}
UPDATE: Actually the above only works if the contact saved is the contact currently tracked by Sitecore Analytics.
in case you have a tracker available and you dont need the update immediately, the following should work (note that the contact is added to the list upon session expiration):
//private const string ContactListTagName = "ContactLists";
var contact = Tracker.Current.Contact;
// Identify
if (contact.Identifiers.IdentificationLevel < ContactIdentificationLevel.Known)
{
Tracker.Current.Session.Identify(email);
}
// Set Email
var contactEmail = contact.GetFacet<IContactEmailAddresses>("Emails");
// Create an email address if not already present
// This can be named anything, but must be the same as "Preferred" if you want
// this email to show in the Experience Profiles backend.
if (!contactEmail.Entries.Contains("Preferred"))
contactEmail.Entries.Create("Preferred");
// set the email
var emailEntry = contactEmail.Entries["Preferred"];
emailEntry.SmtpAddress = email;
contactEmail.Preferred = "Preferred";
// set FirstName and Surname (required for List Manager, "N/A" might not be ideal but I don't know how Sitecore behaves with empty strings)
var personal = contact.GetFacet<IContactPersonalInfo>("Personal");
personal.FirstName = personal.FirstName ?? "N/A";
personal.Surname = personal.Surname ?? "N/A";
// Add preferred language
var preferences = contact.GetFacet<IContactPreferences>("Preferences");
preferences.Language = Context.Language.Name;
// Here is the actual adding to the list by adding tags
using (new SecurityDisabler())
{
var id = ID.Parse("CONTACTLISTID");
contact.Tags.Set(ContactListTagName, id.ToString().ToUpperInvariant());
}
Greetz,
Markus
I am Using MVVM Pattern.
when I select a Country from the listbox1 then second listbox
will display states from the selected country.
ListBox For Country
<pmControls:pmListBox x:Name="countryListBox" Grid.Row="1" Margin="3" ItemsSource="{Binding Countries}" SelectedItem="{Binding SelectedCountry,Mode=TwoWay}" >
<pmControls:pmListBox.ItemTemplate >
<DataTemplate >
<Button Command="{Binding DataContext.GetAllStatesCommand,ElementName=countryListBox}" Margin="3" Width="100" Height="25" Content="{Binding Title}" >
</Button>
</DataTemplate>
</pmControls:pmListBox.ItemTemplate>
</pmControls:pmListBox>
ListBox For State
<pmControls:pmListBox x:Name="stateListBox" Grid.Row="1" Margin="3" ItemsSource="{Binding States}">
<pmControls:pmListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding StateTitle}" ></TextBlock>
</DataTemplate>
</pmControls:pmListBox.ItemTemplate>
</pmControls:pmListBox>
In ModelView these are my commands:
command to get all Countries:
public void getCountries()
{
CountryServiceClient client = new CountryServiceClient();
client.GetCountryDetailsCompleted += (clientS, eventE) =>
{
if (eventE.Error == null)
{
foreach (var item in eventE.Result)
{
countries.Add(item);
}
}
};
client.GetCountryDetailsAsync();
}
command to get all states for selected Country:
public void ExecutegetAllStatesCommand(EventToCommandArgs args)
{
selectedState = new States();
states = new ObservableCollection<States>();
int cntry_id = this.SelectedCountry.Country_Id;
StateServiceClient client = new StateServiceClient();
client.GetStatesCompleted += (clientS, eventE) =>
{
if (eventE.Error == null)
{
foreach (var item in eventE.Result)
{
states.Add(item);
}
}
};
client.GetStatesAsync(cntry_id);
}
Here i got the data correctly in my list states but it doesnt appears on Xaml.
Please help.
You mentioned that the 'states' are being set correctly in the viewmodel, in that case the problem could be one of the following:
I noticed you are binding to 'States' (upper case S) and your code behind sets to 'states' (lower case S).
Have you implemented the INotifyPropertyChanged for the viewmodel and call the propertychanged event handler
Try handling the CollectionChanged of the ObservableCollection that you are adding States to as the propertychanged will not automatically trigger when adding items.