Najprostsza aplikacja Spring JPA mająca front w React

Najprostsza aplikacja Spring JPA mająca front w React
PA
  • Rejestracja:prawie 8 lat
  • Ostatnio:15 dni
  • Postów:132
0

Hej. Próbowałem jakiś czas temu stworzyć jak najprostszą aplikację, w której backend byłby w Springu, a front w React. Program ma tylko jedną funkcję: dla wprowadzonego w pole tekstowe miasta szuka w bazie danych "world" danych dotyczących populacji i wyświetla je.
W React zrobiłem najprostszy formularz zawierający pole tekstowe i miejsce na rezultat. Teraz nie wiem jak to połączyć tak, żeby tekst wprowadzany w pole tekstowe był argumentem dla metody w Javie "findByPopulation" i żeby w polu "Result" był wyświetlany wynik tej metody.
Byłbym bardzo wdzięczny za pomoc. Jeśli dobrze to rozumiem, to powinno być kilka linijek w JavaScripcie w komponentach 'result' dodać coś do '<dev>' i w 'Form' do '<form>, ale ciężko mi się było połapać jak to dokładnie zrobić. Poniżej linki. To jest siedem klas, ale chyba bardzo prostych.

Jakby ktoś sie zastanawiał po co w ogóle mi to. Przejrzałem kilka kursów i jest trochę tak, że kurs Spring Java w momencie, w którym jest omawiany temat komunikacji z frontem, podaje po prostu dosyć złożony (jak dla kogoś kto nigdy nic nie napisał w JavaScript) przykład widoku, który należy sobie wkleić i nie głowić się za bardzo nad tym co tam się dzieje. No ja jednak wolałbym na prostym przykładzie wiedzieć jak pola z klas w JS są identyfikowane z tymi w Javie, a poza tym stopniowo sobie wszystko rozbudowywać.

Kopiuj
    class App extends Component {
  render (){
  return(
    <div className='App'>
  <Form />
 <Result />
 </div>
  );
}
}
Kopiuj
const Form = () => {
    return (
        <form>
            <input type='text'/>
            <button>Wyszukaj miasto</button>
        </form>

    )
}

export default Form;
Kopiuj
const Result = () => {

    return (
        <div>Populacja</div>
    );
}

export default Result;
Kopiuj
mport lombok.*;
import javax.persistence.*;

@Entity
@Table(name = "city")
@Getter
@Setter
@ToString


public class City {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    int ID;
    String name;
    @Transient
    String CountryCode;
    String District;
    int Population;

    public City()
    {

    }

    public City(int ID, String name, /*String countryCode,*/ String District, int Population) {
        this.ID = ID;
        this.name = name;
        /*this.CountryCode = countryCode;*/
        this.District = District;
        this.Population = Population;
    }
}
Kopiuj
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface CityRepository extends JpaRepository<City, Long> {

    List<City> findByName(String name);
    List<City> findByPopulation(int population);

}
Kopiuj
@RestController
public class CityService {

    @Autowired
    CityRepository cityRepository;

    @Autowired
    ObjectMapper objectMapper;

     @PostMapping("/cities")
    public ResponseEntity findCity(@RequestBody City city){
        List <City> foundedCity = cityRepository.findByName(city.getName());
        return ResponseEntity.ok(foundedCity);
    }

}
Kopiuj
@SpringBootApplication
public class Main {


    public static void main(String[] args) {
        SpringApplication.run(Main.class, args);

    }
}
edytowany 1x, ostatnio: paranoise
Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:35 minut
  • Postów:1873
1

Na pierwszy rzut oka widać, że to nie zagra. Napisz na jakim jesteś etapie - odpaliłeś to i jaki błąd dostajesz?

Ogólna uwaga - podczas nauki skup się na jednej rzeczy. W tym przypadku najpierw nauczyłbym się wystawiać Rest API w Springu i potestował to curlem/Postmanem, a dopiero potem zaczął naukę Reacta. Albo odwrotnie. Jedno i drugie trochę Ci zajmie, więc po kolei.


”Engineering is easy. People are hard.” Bill Coughran
edytowany 4x, ostatnio: Charles_Ray
EZ
  • Rejestracja:około 5 lat
  • Ostatnio:ponad 4 lata
  • Postów:32
1

Zdefiniowałeś sobie endpoint (klasa CityService), który odpowiada na żądania http. Teraz z aplikacji React musisz wysłać żądanie na ten endpoint, a w odpowiedzi dostaniesz listę, którą sobie pobierasz z repozytorium. Parametry metody findCity z klasy CityService stanowią ciało żądania które wysyłasz, pomijając fakt, że używasz do tego celu encji w żądaniu musisz umieścić name za pomocą którego wyszukujesz w repozytorium. Żądanie możesz wysłać np. za pomocą Fetch API.

dodam jeszcze, że pewnie używasz serwera deweloperskiego Reacta, więc będziesz musiał sobie skonfigurować proxy w pliku package.json, wystarczy dodać linijkę: "proxy": "http://{host}:{port}", np. "proxy": "http://localhost:8080"

edytowany 1x, ostatnio: eziomou
PA
  • Rejestracja:prawie 8 lat
  • Ostatnio:15 dni
  • Postów:132
0
eziomou napisał(a):

Zdefiniowałeś sobie endpoint (klasa CityService), który odpowiada na żądania http. Teraz z aplikacji React musisz wysłać żądanie na ten endpoint, a w odpowiedzi dostaniesz listę, którą sobie pobierasz z repozytorium. Parametry metody findCity z klasy CityService stanowią ciało żądania które wysyłasz, pomijając fakt, że używasz do tego celu encji w żądaniu musisz umieścić name za pomocą którego wyszukujesz w repozytorium. Żądanie możesz wysłać np. za pomocą Fetch API.

dodam jeszcze, że pewnie używasz serwera deweloperskiego Reacta, więc będziesz musiał sobie skonfigurować proxy w pliku package.json, wystarczy dodać linijkę: "proxy": "http://{host}:{port}", np. "proxy": "http://localhost:8080"

Do tej pory coś podobnego robiłem w Javie EE i HTML-u, no i miałem cichą nadzieję, że jednak jest jakieś podobne rozwiązanie, tj. w klamrach formularza napisanego w React mam identifikator "name", któremu nadaję nazwę "city" i potem w metodzie Springa odbiorę to mniej więcej tak

Kopiuj
String searchedCity = request.getParameter("city");

Potem w Springu metoda wyszukuje mi dla danego miasta populację, zapisuję je jako String "popution" i wysyłam coś w stylu:

Kopiuj
Response resp = new Resp();
resp.send(population);

Potem na podobnej zasadzie pobieram do widoku w React, to co wysłałem z kodu Javy. No jednak jak czytam tutoriale z Reacta, to chociaż niby jest zalecany dla osób, które nie chcą się wgłębiać w JavaScript i chcą tylko sobie zrobić prosty front, żeby coś na nim przetestować, to próbując znaleźć jakieś najprostsze odpowiedzi łapię się na tym, że najlepiej byłoby przerabiać wszystko od podstaw. :(

edytowany 1x, ostatnio: paranoise
Gustlik44
Jeżeli nie chcesz zagłębiać się w JS to może Vaadin?
AK
Apache Wicket !, Apache Wicket !
Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:35 minut
  • Postów:1873
1

To co chcesz zrobić jest osiągalne po przerobieniu tutoriala ze strony Reacta, który zahacza o komunikacje z API, a wiec niezbędne podstawy możesz nabyć w 1-2 wieczory.


”Engineering is easy. People are hard.” Bill Coughran
PA
  • Rejestracja:prawie 8 lat
  • Ostatnio:15 dni
  • Postów:132
0

dodam jeszcze, że pewnie używasz serwera deweloperskiego Reacta, więc będziesz musiał sobie skonfigurować proxy w pliku package.json, wystarczy dodać linijkę: "proxy": "http://{host}:{port}", np. "proxy": "http://localhost:8080"

Ale jak? Jak wklejam przed wszystkim na samym początku to od razu mi podkreśla jako błąd kompilacji. Jeśli chcę to wpakować w którąś klamrę też. Z resztą czy aby nie jest tak, że sobie w SpringBoocie mogę ustawić w Properties localhost na dowolny, tyle żeby był identyczny z tym, do którego odwołuje się kod w React i wszystko będzie działać?

Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:35 minut
  • Postów:1873
0

To nie to samo. Nie jestem frontendowcem, ale serwer developerski daje Ci np. hot reload assetów. https://create-react-app.dev/docs/proxying-api-requests-in-development/


”Engineering is easy. People are hard.” Bill Coughran
EZ
bardziej chodziło mi o cors ale to też
Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:35 minut
  • Postów:1873
1

A tak w ogóle jeszcze, wpisałem w Google „spring react” i wyskoczył mi tutorial do Spring Data Rest ze słabej jakości frontem w React: https://spring.io/guides/tutorials/react-and-spring-data-rest/ Może Cię usatysfakcjonuje, przynajmniej miałbyś jakikolwiek front stukający do API.


”Engineering is easy. People are hard.” Bill Coughran
PA
  • Rejestracja:prawie 8 lat
  • Ostatnio:15 dni
  • Postów:132
0

No ok. Dzięki wszystkim. Zaraz się biorą za Reacta od podstaw, ale mam jeszcze pytanie - jak Spring odbiera zapytanie? Jak to się robi, że np. Front w React stoi na localhost:3000, backend w Springu na 8080 i to razem działa? Jeśli dam w Springu server.port=3000, a w React to jest port domyślny to z oczywistych przyczyn projekt nie ruszy. Próbowałem w ten sposób, że skoro jeśli wpiszę w formularzu i wyśle "Poznań" to w adresie będę miał: "http://localhost:3000/?city=Poznań", to żeby odebrać te słowo i wydrukować je w konsoli, powinienem zrobić coś takiego

Kopiuj
@RestController
public class CityService {

    @Autowired
    CityRepository cityRepository;

    @Autowired
    ObjectMapper objectMapper;
    @GetMapping("/?city={name}")
    public void getCity(@PathVariable String name) 
    {
        System.out.println(name);
    }
}

Tyle, że wtedy Spring będzie to interpretował jako "localhost:8080/?city={name}". Podejrzewam, że albo trzeba coś ustawić w konfiguracji, albo po prostu nad metodą można dać jakąś adnotację wskazującą na port 3000.

edytowany 1x, ostatnio: paranoise
Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:35 minut
  • Postów:1873
0

Masz ustawione proxy na port 8080, ot cała magia. Przeczytałeś link, który podałem, czy olałeś sprawę? :)
https://create-react-app.dev/docs/proxying-api-requests-in-development/


”Engineering is easy. People are hard.” Bill Coughran
nowyworek
  • Rejestracja:prawie 5 lat
  • Ostatnio:ponad 4 lata
  • Lokalizacja:świat
  • Postów:174
0
paranoise napisał(a):

No ok. Dzięki wszystkim. Zaraz się biorą za Reacta od podstaw, ale mam jeszcze pytanie - jak Spring odbiera zapytanie? Jak to się robi, że np. Front w React stoi na localhost:3000, backend w Springu na 8080 i to razem działa? Jeśli dam w Springu server.port=3000, a w React to jest port domyślny to z oczywistych przyczyn projekt nie ruszy. Próbowałem w ten sposób, że skoro jeśli wpiszę w formularzu i wyśle "Poznań" to w adresie będę miał: "http://localhost:3000/?city=Poznań", to żeby odebrać te słowo i wydrukować je w konsoli, powinienem zrobić coś takiego

Kopiuj
@RestController
public class CityService {

    @Autowired
    CityRepository cityRepository;

    @Autowired
    ObjectMapper objectMapper;
    @GetMapping("/?city={name}")
    public void getCity(@PathVariable String name) 
    {
        System.out.println(name);
    }
}

Tyle, że wtedy Spring będzie to interpretował jako "localhost:8080/?city={name}". Podejrzewam, że albo trzeba coś ustawić w konfiguracji, albo po prostu nad metodą można dać jakąś adnotację wskazującą na port 3000.

Jeszcze dodam, zrób zależności private final i dodaj konstruktor można wtedy też usunać @Autowired.
I Zamiast ?city=name użyj @RequestParam String city


Julian
PA
  • Rejestracja:prawie 8 lat
  • Ostatnio:15 dni
  • Postów:132
0

No ok. Jest postęp. @Charles_Ray przeglądałem ten projekt, tylko, że nie zjarzyłem w jaki sposób tam jest wszystko na jednym localhoście. Koniec końców zrobiłem to przez @CrossOrigin w Springu i chyba to jest najbardziej typowe rozwiązanie. Zrobiłem jeszcze stejta w React, ale nie mogę zapisać w nim danych przekazanych przez Springa. Tak wygląda formularz i klasa startowa w React:
App.js

Kopiuj
class App extends Component {

  constructor(props) {
    super(props);
    this.state = {
       population: '',
       district: ''
    };
    this.handleInputChange = this.handleInputChange.bind(this);
    this.handleCitySubmit = this.handleCitySubmit.bind(this);
 }

state = {
  district: '',
  population: '',
}

handleInputChange = (e) => {
  this.setState({
    value: e.target.value
  })
}

handleCitySubmit = e => {
  e.preventDefault()
  const API = `http://localhost:8080/cities`;

  fetch(API)
  .then(response => {
    if(response.ok){
  return response
}
throw Error("It doesn't works")
  })
  .then(response => response.json())
  .then(data => {
    this.setState({
      district: data.district,
      population: data.population

    })
  })
console.log('District info: '+this.state.district)
console.log('Population info: '+this.state.population)
}


  render (){
    return (
    <div className="App">
      <Form 
      value = {this.state.value}
      submit = {this.handleCitySubmit}
      />
      <Result/>
    </div>
  );
    }
}

export default App

Form.js

Kopiuj
import React from 'react';

const Form = props => {
return (
    <form onSubmit={props.submit}>
        <input 
        type ="text" 
        value = {props.value}
        placeholder="Enter city name"
        />
        <button>Find city </button>
    
    </form>
)
}

export default Form

A tak kontroler Springa:

Kopiuj
@RestController
public class CityService {

    @Autowired
    CityRepository cityRepository;

    @Autowired
    ObjectMapper objectMapper;

    @CrossOrigin(origins = "http://localhost:3000")
    @GetMapping("/cities")
    public ResponseEntity getCity ()throws JsonProcessingException
    {
        List <City> cities = cityRepository.findByName("New York");
        System.out.println(cities);
        return ResponseEntity.ok(objectMapper.writeValueAsString(cities));
    }
}

Tego @RequestParam użyję jak opanuję w jaki sposób dane z formularza wysyłać do metody w Springu. Na razie będę szczęśliwy jak dane ze Springa zostaną odebrane poprawnie. Trochę to dla mnie dziwne, bo jak wchodzę na > http://localhost:8080/cities
to wyświetla mi poprawnie: [{"name":"New York","countryCode":null,"population":8008278,"id":3793,"district":"New York"}], ale kiedy odbieram to przez formularz React na localhost:3000 i robię w przeglądarce "inspect" to dostaję informację, że district i population są niezdefiniowane. Ktoś wie czemu i jak to naprawić?

edytowany 1x, ostatnio: paranoise
nowyworek
  • Rejestracja:prawie 5 lat
  • Ostatnio:ponad 4 lata
  • Lokalizacja:świat
  • Postów:174
0
paranoise napisał(a):

No ok. Jest postęp. @Charles_Ray przeglądałem ten projekt, tylko, że nie zjarzyłem w jaki sposób tam jest wszystko na jednym localhoście. Koniec końców zrobiłem to przez @CrossOrigin w Springu i chyba to jest najbardziej typowe rozwiązanie. Zrobiłem jeszcze stejta w React, ale nie mogę zapisać w nim danych przekazanych przez Springa. Tak wygląda formularz i klasa startowa w React:
App.js

Kopiuj
class App extends Component {

  constructor(props) {
    super(props);
    this.state = {
       population: '',
       district: ''
    };
    this.handleInputChange = this.handleInputChange.bind(this);
    this.handleCitySubmit = this.handleCitySubmit.bind(this);
 }

state = {
  district: '',
  population: '',
}

handleInputChange = (e) => {
  this.setState({
    value: e.target.value
  })
}

handleCitySubmit = e => {
  e.preventDefault()
  const API = `http://localhost:8080/cities`;

  fetch(API)
  .then(response => {
    if(response.ok){
  return response
}
throw Error("It doesn't works")
  })
  .then(response => response.json())
  .then(data => {
    this.setState({
      district: data.district,
      population: data.population

    })
  })
console.log('District info: '+this.state.district)
console.log('Population info: '+this.state.population)
}


  render (){
    return (
    <div className="App">
      <Form 
      value = {this.state.value}
      submit = {this.handleCitySubmit}
      />
      <Result/>
    </div>
  );
    }
}

export default App

Form.js

Kopiuj
import React from 'react';

const Form = props => {
return (
    <form onSubmit={props.submit}>
        <input 
        type ="text" 
        value = {props.value}
        placeholder="Enter city name"
        />
        <button>Find city </button>
    
    </form>
)
}

export default Form

A tak kontroler Springa:

Kopiuj
@RestController
public class CityService {

    @Autowired
    CityRepository cityRepository;

    @Autowired
    ObjectMapper objectMapper;

    @CrossOrigin(origins = "http://localhost:3000")
    @GetMapping("/cities")
    public ResponseEntity getCity ()throws JsonProcessingException
    {
        List <City> cities = cityRepository.findByName("New York");
        System.out.println(cities);
        return ResponseEntity.ok(objectMapper.writeValueAsString(cities));
    }
}

Tego @RequestParam użyję jak opanuję w jaki sposób dane z formularza wysyłać do metody w Springu. Na razie będę szczęśliwy jak dane ze Springa zostaną odebrane poprawnie. Trochę to dla mnie dziwne, bo jak wchodzę na > http://localhost:8080/cities
to wyświetla mi poprawnie: [{"name":"New York","countryCode":null,"population":8008278,"id":3793,"district":"New York"}], ale kiedy odbieram to przez formularz React na localhost:3000 i robię w przeglądarce "inspect" to dostaję informację, że district i population są niezdefiniowane. Ktoś wie czemu i jak to naprawić?

Kopiuj
@RestController
public class CityController {
    private final CityRepository cityRepository;

    public CityController(final CityRepository repo) {
        cityRepository=repo;
   }

    @GetMapping("/cities")
    ResponseEntity<List<Cities>> getCities () {
       var cities = cityRepository.findByName("New York"); 
       return ResponseEntity.ok(cities);
   }
}

To jest poprawne, a jak chcesz parama na nazwę miasta to:

Kopiuj
@RestController
public class CityController {
    private final CityRepository cityRepository;

    public CityController(final CityRepository repo) {
        cityRepository=repo;
   }

    @GetMapping("/cities")
    ResponseEntity<List<Cities>> getCities (@RequestParam String name) {
       var cities = cityRepository.findByName(name); 
       return ResponseEntity.ok(cities);
   }
}

A request wygląda tak GET http://{nazwaHosta}:{port}/cities?name={nazwaMiasta}

Jeszcze jedno nigdy, na prawde nigdy tej adnotacji na corsa nie uzywaj poza testami jakimis i szybkim prototypowaniem. To jest niesamowity syf w kodzie potem. Corsa sie robi w konfiguracji WebMvcConfigurer .


Julian
edytowany 3x, ostatnio: nowyworek
PA
  • Rejestracja:prawie 8 lat
  • Ostatnio:15 dni
  • Postów:132
0

@nowyworek: No ale co to zmienia? W state dalej nie mam zapisanych district i population.

Charles_Ray
Zobacz w konsoli przeglądarki co zwraca backend. Na oko leci tam lista, a Ty przypisujesz do state atrybuty pojedynczego obiektu?
PA
  • Rejestracja:prawie 8 lat
  • Ostatnio:15 dni
  • Postów:132
0

@nowyworek: Jeśli dobrze Cię rozumiem, to muszę albo zrobić tak, żeby ResponseEntity zawierał pojedynczy obiekt albo w metodzie Reacta wskazać najpierw, do którego elementu tablicy chcę się odwołać, a dopiero później pobrać wartość z kluczy population i district. No w React próbowałem tak:

Kopiuj
  .then(data => {
    this.setState({
      district: data[0].district,
      population: data[0].population

    })

no i nie działa. Z drugiej strony próbowałem przekazać pojedynczy obiekt, zamiast listy w ResponseEntity o tak:

Kopiuj
    ResponseEntity<City> getFirstCity()
    {
        Long number = Long.valueOf(3793);
        Optional<City> city = cityRepository.findById(number);
        return ResponseEntity.ok(city);
    }

No i też nie działa już na etapie kompilacji i nie kumam tego błędu, który mi wskazuje kompilator. :(

edytowany 1x, ostatnio: paranoise
Charles_Ray
LOL to może pokaz ten błąd kompilacji :)
Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:35 minut
  • Postów:1873
1

Dajesz nam za mało danych. Czy możesz pobrać dane z backendu za pomocą np curla albo postmana? Sprawdz w konsoli Chrome/FF (zakładka Network) co się dzieje na froncie, przychodzą tam te dane?


”Engineering is easy. People are hard.” Bill Coughran
PA
  • Rejestracja:prawie 8 lat
  • Ostatnio:15 dni
  • Postów:132
0

@Charles_Ray:

Kopiuj
no instance(s) of type variable(s) exist so that Optional<City> conforms to City inference variable T has incompatible bounds: equality constraints: City lower bounds: Optional<City>
Shalom
No panie Optional<T> to nie T. Na optionalu musisz zrobić jakieś .get() żeby dostać obiekt (o ile nie jest pusty!). Masz niżej mój post jak to poprawić.
PA
  • Rejestracja:prawie 8 lat
  • Ostatnio:15 dni
  • Postów:132
0
Charles_Ray napisał(a):

Dajesz nam za mało danych. Czy możesz pobrać dane z backendu za pomocą np curla albo postmana? Sprawdz w konsoli Chrome/FF (zakładka Network) co się dzieje na froncie, przychodzą tam te dane?

No tak. Tak to wygląda w Postmanie:
body:

Kopiuj
[
    {
        "name": "New York",
        "countryCode": null,
        "population": 8008278,
        "id": 3793,
        "district": "New York"
    }
]

Nagłówków jest osiem. Pierwsze trzy nazywające się "vary" mają wartość: origin, Access-Control-Request-Method, Access-Control-Request-Method. Następnie Content-Type: application/json, Transfer-Encoding: chunked, Date - no wiadomo, data godzina, Keep-Alive: timout=60, Connection: keep-Alive.

A no i status 200 ok. A wiem, że w ogóle się komunikuje front z backendem przez to, że kiedy klikam ten przycisk w formularzu, to jeśli mam w tej metodzie w Springu coś w stylu:

Kopiuj
System.out.println("Wyświetl coś");

No to wyświetla w konsoli Intellij.

Oooo! Zadziałało. Ale nie wiem czemu za którymś tam kliknięciem. Czyli szanowny kolega @nowyworek miał rację z tym, że wystarczy w React zaznaczyć, do którego elementu listy się odwołuję.

Charles_Ray
Ja Ci to napisałem ze w Reactie odwołujesz się do pojedynczego elementu zamiast do listy, ale nieważne :) jak działa to git. Wcześniej w konsoli Chrome na pewno leciał błąd
Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
3
Kopiuj
        Optional<City> city = cityRepository.findById(number);
        return ResponseEntity.ok(city);

Tak to sie nie da. ResponseEntity.of(city) a nie ok(). Skąd wiesz że ok skoro optional może być pusty?!


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)